Authored by xwx

Merge branch 'master-500-dev' of http://113.200.75.45:82/monitor_v3/hg-monitor-w…

…eb into master-500-dev-xwx
... ... @@ -3204,6 +3204,7 @@ layui.define(['laytpl', 'admin', 'form', 'table', 'echarts', 'sessions', 'xmSele
}
title += `<a class="layui-icon filterList" data-id=${resId} lay-tips="指标过滤清单" style="margin-left: 10px"><i class="iconfont">&#XE516;</i></a>`;
title += `<a class="layui-icon res-view-relation-topo" data-id=${resId} lay-tips="查看资源关系拓扑" style="margin-left: 10px"><i class="iconfont">&#XE515;</i></a>`;
title += `<a class="layui-icon res-view-ping" data-id=${resId} data-resName=${name} data-ip=${ip} data-resTypeName=${res.resTypeName} data-adminName=${res.adminName} lay-tips="查看资源ping详情" style="margin-left: 10px"> <img width="20" src="/src/style/img/ping.png" ></a>`;
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">&#XE517;</i></a>`;
... ... @@ -3494,6 +3495,28 @@ layui.define(['laytpl', 'admin', 'form', 'table', 'echarts', 'sessions', 'xmSele
}
common.viewResTopo($(this).data('id'));
});
//start 查看ping详情列表页 lsq 2022-04-24
$('a.res-view-ping').unbind('click').on('click', function () {
// if ($.inArray('back:details:viewtopo', checkList) === -1) {
// layer.msg('暂无权限!', {icon: 0});
// return;
// }
let paramStr='?resId='+$(this).data('id')+'&resName='+$(this).data('resName')+'&resTypeName='+$(this).data('resTypeName')+'&adminName='+$(this).data('adminName')+'&ip='+$(this).data('ip')
layer.open({
title: ['ping详情', 'font-size:18px;'],
type: 2,
area: ['80%', '90%'],
shadeClose: true,//开启遮罩层
id: 'res-ping',
// content: laytpl(res.body).render(JSON.stringify(params)),
content: ['/vue3/index.html#/ping'+paramStr, 'no'],
cancel: function () {
clearTimeout();
}
});
});
//end lsq 2022-04-24
// 查看资产配置信息
$('a.res-view-assets-details').unbind('click').on('click', function () {
... ...
... ... @@ -15,4 +15,26 @@
}
.protocol-btn i{
color:#ffffff;
}
.expand-container{
padding:5px 10px;
}
.expand-container .margin-top{
margin-top:10px;
}
.expand-container .el-descriptions__header{
padding:5px;
background: #F1F6F9;
margin-bottom: 0px;
}
.expand-container .el-descriptions__title{
font-size:14px;
font-weight: normal;
}
.cmdb-descriptions{
width:300px;
}
.cmdb-descriptions .star{
font-size:14px;
color:#d81e06;
}
\ No newline at end of file
... ...
... ... @@ -115,6 +115,12 @@ const routes = [{
name: 'cmdbdatasync',
component: () => myImport('views/cmdbdatasync/index'),
},
//ping详情列表
{
path: '/ping',
name: 'pingIndex',
component: () => myImport('views/ping/index'),
},
];
// hash模式: createWebHashHistory
... ...
... ... @@ -15,7 +15,41 @@
:expands="tableData.expands"
:height="height - 110">
<template #expand="{scope}">
aaa{{scope.row.expand}}
<div class="expand-container" style="width:50%;">
<el-descriptions
class="margin-top"
:title="item.protocolName"
:column="1"
:size="''"
border
v-for="item in scope.row.extend"
:key="item.protocolId"
>
<template #extra>
<!-- <el-button type="primary">Operation</el-button>-->
</template>
<el-descriptions-item label-class-name="cmdb-descriptions" v-for="itemChild in item.protocolParamList" :key="itemChild.collParamId">
<template #label>
<div class="cell-item">
{{itemChild.paramName}}
<!--<span class="star">*</span>-->
</div>
</template>
<el-input style="width: 220px;" v-model="itemChild.defaultValue" size="small"/>
<!-- <el-input style="width: 220px;" v-if="itemChild.inputWay=='input'" v-model="itemChild.defaultValue" size="small"/>
<el-select size="small" v-else-if="itemChild.inputWay=='select'" v-model="itemChild.defaultValue" class="m-2" placeholder="请选择">
<el-option
v-for="itemDdic in optinos"
:key="itemDdic.ddicCode"
:label="itemDdic.ddicName"
:value="itemDdic.ddicCode"
/>
</el-select>
<span v-else>{{itemChild.defaultValue}}</span>-->
</el-descriptions-item>
</el-descriptions>
</div>
</template>
<template #default="{row,prop,column}">
<div>
... ... @@ -31,7 +65,7 @@
</template>
<template #tools="{scope}">
<div class="protocol-btn">
<span class="icon-add" @click="addProtocol" title="协议参数"><i class="el-icon-plus"></i></span>
<span class="icon-add" @click="addProtocol(scope.row)" title="协议参数"><i class="el-icon-plus"></i></span>
</div>
</template>
</cm-table-page>
... ...
... ... @@ -14,20 +14,62 @@ export default {
const {proxy} = Vue.getCurrentInstance();
let height = Vue.ref(window.innerHeight);
let editTbaleData=Vue.ref(props.tableData.dataList);
let resType=Vue.ref(props.tableData.resType);
// let columns=Vue.ref(props.tableData.columns);
// let getRowKeys=Vue.ref(props.tableData.getRowKeys);
// let expands=Vue.ref(props.tableData.expands);
//保存编辑
let saveEdit=()=>{
//保存接口 todo
let param={
editTbaleData:editTbaleData.value,
visibility:false
let idList='';
let idArr=[];
if(editTbaleData.value && editTbaleData.value.length>0){
editTbaleData.value.map(item=>{
idArr.push(item.id)
})
}
emit("callbackedit",param)
if(idArr.length>0){
idList=idArr.join(',')
}
/*let param={
// resType:resType.value,
// idList:idList,
bean:editTbaleData.value
}*/
let data=editTbaleData.value;
let arr=[];
data.map(item=>{
if(item.proto && item.proto.length>0){
item.proto.map(item=>{
item.paramValue=item.defaultValue;
item.protocol=item.protocolId;
})
}
arr.push({
bean:item,
proto:item.proto
})
})
let param=arr;
proxy.$http.post( '/api-web/cmdbSync/toMonitor1',param, function (res) {
if (res && res.success) {
proxy.$global.showMsg('保存成功','success');
}else{
proxy.$global.showMsg('保存失败','error');
}
let backData={
editTbaleData:editTbaleData.value,
visibility:false
}
emit("callbackedit",backData)
});
}
//添加协议
let addProtocol=()=>{
let clickResId=Vue.ref('');
let addProtocol=(row)=>{
clickResId.value=row.resId;
proxy.$global.layer.open({
title:'资源协议',
id:'resManageChooseProtocolHtml',
... ... @@ -39,20 +81,50 @@ export default {
proxy.$global.layui.view('resManageChooseProtocolHtml').render('/baseconfig/protocol/index',{'hasParam':'1'});
},
yes:function (index,layero) {
var data = proxy.$global.layui.table.checkStatus('protocol_table').data;
formData.ip = $('#resManageAddForm').find('input[name="ip"]').val();
formData.port = $('#resManageAddForm').find('input[name="port"]').val();
let data = proxy.$global.layui.table.checkStatus('protocol_table').data;
proxy.$global.layui.use('resManageAdd', function (fn) {
// console.log("&&&&!!!!",data,fn(row))
// console.log(fn(row).createProtocolDom)
})
let ip = row.ip;
let port = row.port;
if(data.length>0){
createProtocolDom(data,false);
form.render()
layer.close(index);
/*createProtocolDom(data,false);
proxy.$global.layui.form.render()*/
editTbaleData.value.map(item=>{
// item.bean=item;
if(item.resId==row.resId){
let arr=[]
data.map(v=>{
arr=arr.concat(v.protocolParamList.flat());
})
item.extend=data;
item.proto=arr;
}
})
proxy.$global.layer.close(index);
}else{
layer.msg("无选中的数据或当",{ offset: '15px' , icon: 7 , time: 2000 })
proxy.$global.layer.msg("无选中的数据或当",{ offset: '15px' , icon: 7 , time: 2000 })
return false;
}
}
})
}
//协议参数中select的字典数据
let getSelectData=(param)=>{
proxy.$http.post( '/api-web/manage/ddic/findSucDdics/'+param.defaultValue, {}, function (res) {
if (res && res.data) {
let selectData= res.data;
// protocolParamList
}else{
proxy.$global.showMsg('暂无数据','error');
}
});
}
// 挂载完
Vue.onMounted(() => {
})
... ... @@ -61,9 +133,12 @@ export default {
return {
height,
editTbaleData,
resType,
// columns,
saveEdit,
addProtocol,
clickResId,
getSelectData
// getRowKeys,
// expands
}
... ...
<div class="container" :style="{'height':height+'px','max-height':height+'px','display':'flex'}">
<div class="async-left-tree" style="width:200px;overflow-x: auto;background: #fff;border-right:1px solid #f2f2f2;">
<el-tree style="padding-top:10px;" class="tree-div" ref="roleTree" :data="treeData" :props="defaultProps" @node-click="handleNodeClick"
node-key="id" :default-checked-keys="checkedKeys"
<el-tree ref="datasyncTree" style="padding-top:10px;" class="tree-div" ref="roleTree" :data="treeData" :props="defaultProps" @node-click="handleNodeClick"
node-key="id" :current-node-key="checkedKeys" :default-expanded-keys="expendKeys" :highlight-current="true"
/>
</div>
<div class="cm-card" :style="{'min-height':height+'px','max-height':height+'px','height':'100%','padding-top':'3px','flex':'1'}">
<div class="search">
<div class="condition">
<el-form-item >
<el-input v-model="search.keyword" placeholder="关键字"></el-input>
<el-input style="width:120px;" v-model="search.keyword" placeholder="关键字"></el-input>
</el-form-item>
<el-form-item >
<el-select style="width:200px;" v-model="search.provider" class="m-2" placeholder="厂商" clearable>
<el-option
v-for="item in providerData"
:key="item.ddicCode"
:label="item.ddicName"
:value="item.ddicCode"
/>
</el-select>
</el-form-item>
<el-form-item >
<el-select style="width:200px;" v-model="search.system" class="m-2" placeholder="系统" clearable>
<el-option
v-for="item in systemData"
:key="item.ddicCode"
:label="item.ddicName"
:value="item.ddicCode"
/>
</el-select>
</el-form-item>
<el-form-item >
<el-select style="width:200px;" v-model="search.resSyncState" class="m-2" placeholder="资源处理状态" clearable>
<el-option
v-for="item in resSyncStateData"
:key="item.ddicCode"
:label="item.ddicName"
:value="item.ddicCode"
/>
</el-select>
</el-form-item>
<el-form-item >
<el-button @click="getDataList">查询</el-button>
</el-form-item>
<el-form-item >
<el-button @click="handleEdit">编辑</el-button>
<el-button @click="handleEdit">纳入监控</el-button>
</el-form-item>
<el-form-item >
<el-button @click="handleRefresh">同步</el-button>
</el-form-item>
<el-form-item >
<el-button @click="handleIgnore">忽略</el-button>
</el-form-item>
</div>
</div>
<div class="search-table">
<cm-table-page :columns="tableData.columns" :dataList="tableData.dataList"
<cm-table-page v-if="tableData.dataList " :columns="tableData.columns" :dataList="tableData.dataList"
:showIndex="true"
:total="tableData.count"
@loaddata = "loaddata"
... ... @@ -30,7 +63,7 @@
:showSelection="true"
:showBorder="true"
:loading="false"
:pageSize="pageSize"
:pageSize="search.pageSize"
:showPage="true"
:showTools="true"
:height="height - 110">
... ... @@ -41,7 +74,6 @@
</template>
<template #tools="{scope}">
<div class="list-handle">
<span class="icon-bg" @click="handleEdit(1,scope.row)"><i class="el-icon-edit-outline" title="编辑"></i></span>
<span class="icon-bg" @click="handleRefresh(1,scope.row)"><i class="el-icon-refresh" title="同步"></i></span>
</div>
</template>
... ... @@ -53,7 +85,7 @@
<!--弹框-->
<cm-dialog :title="dialog.title" width="90%" :showDialogVisible="dialog.show" @hidedialog="hideDialog" :showFooter="false">
<template v-slot>
<cmdbdatasyncEdit :tableData="dialog.tableData" @callbackedit="callbackedit"/>
<cmdbdatasyncEdit v-if="dialog.tableData && dialog.tableData.dataList.length>0" :tableData="dialog.tableData" @callbackedit="callbackedit"/>
</template>
</cm-dialog>
... ...
... ... @@ -14,40 +14,42 @@ export default {
children: 'children',
label: 'title'
})
let treeData=Vue.ref([]) // 所有的树结点
let treeData=Vue.ref([]) // 所有的树节点
let checkedKeys=Vue.ref('');//默认选中的树节点
let expendKeys=Vue.ref([]);//默认展开的树节点
let defaultNode=Vue.ref(true);//默认节点
let resType=Vue.ref('');//选中的树节点值
let resTypeName=Vue.ref('');//选中的树节点值名称
let handleNodeClick=(data,node)=>{
//点击树节点,根据某个字段获取列表 todo
console.log("*(*(*(*",data,node)
proxy.$global.showMsg(data.id,'warning')
//点击树节点,根据某个字段获取列表
resType.value=data.value;
resTypeName.value=data.title;
defaultNode.value=false;
getDataList();
}
let providerData=Vue.ref([]);//厂商
let systemData=Vue.ref([]);//系统
let resSyncStateData=Vue.ref([]);//资源处理状态
let currentPage=Vue.ref(1);//当前页
let search = Vue.ref({
keyword: '',
pageNum: 1,
pageSize: 20,
resSyncState:'',
system: '',
provider:'',
});
//表格字段
let tableData = Vue.ref({
count:0,
dataList: [{
id:1,
resName:'资源一'
},{
id:2,
resName:'资源34'
}],
dataList: [],
columns: [
{
prop: 'resName',
label: '资源名称',
sortable: true,
align: 'center',
width: '250'
width: '200'
},
{
prop: 'resTypeName',
... ... @@ -56,31 +58,98 @@ export default {
align: 'center',
width: '200'
}, {
prop: 'host',
label: 'IP地址',
prop: 'resCategory',
label: '资源分类',
sortable: true,
align: 'center',
width: '200'
}, {
prop: 'type',
label: '日志来源',
width: '100'
},
{
prop: 'ip',
label: 'ip',
sortable: true,
align: 'center',
width: '200'
},
{
prop: 'program',
label: '日志类型',
prop: 'port',
label: '端口',
sortable: true,
align: 'center',
},
{
prop: 'os',
label: '操作系统类型',
sortable: true,
align: 'center',
width: '130'
},
{
prop: 'provider',
label: '厂商',
sortable: true,
align: 'center',
width: '100'
},
{
prop: 'state',
label: '资源处理状态',
sortable: true,
align: 'center',
width: '130',
render:function (row){
let str='已同步';
if(row.state=='1'){
str='纳入监控';
}else if(row.state=='2'){
str='忽略';
}else{
str='已同步';
}
return `<span>${str}</span>`
}
},
{
prop: 'synctype',
label: 'cmdb数据同步类型',
sortable: true,
align: 'center',
width: '200',
render:function (row){
let str='自动同步';
if(row.synctype=='1'){
str='手动同步';
}else if(row.synctype=='2'){
str='自动覆盖同步';
}else if(row.synctype=='3'){
str='手动覆盖同步';
}else{
str='自动同步';
}
return `<span>${str}</span>`
}
},
{
prop: 'resSyncDate',
label: '资源处理时间',
sortable: true,
align: 'center',
width: '200'
},
{
prop: 'message',
label: '日志内容',
prop: 'syncDate',
label: 'CMDB数据同步时间',
sortable: true,
align: 'center',
width: '200'
},
{
prop: 'remark',
label: '备注',
sortable: true,
align: 'center',
width: '200'
}
]
})
let dialog = Vue.ref({
... ... @@ -91,9 +160,20 @@ export default {
let loaddata = ({page, limit}) => {
search.value.pageNum = page;
search.value.pageSize = limit;
getDataList();
}
let hideDialog = (flg) => {
let hideDialog = (flg,isSave) => {
dialog.value.show = flg;
if(isSave){
setData();
}
}
//设置为空
let setData=()=>{
dialog.value.tableData.dataList=[];
tableData.value.dataList=[];
selectionData.value=[];
getDataList();
}
//全选事件
let selectionData=Vue.ref([]);//选择的数据
... ... @@ -102,17 +182,18 @@ export default {
}
// 处理弹框
let handle = (row) =>{
hideDialog(true);
dialog.value.tableData.dataList= row;
dialog.value.tableData.columns=tableData.value.columns;
dialog.value.tableData.getRowKeys= 'id';
dialog.value.tableData.resType= resType.value;
dialog.value.tableData.resTypeName=resTypeName.value;
let arr=[];
row.map(item=>{
arr.push(item.id)
})
//默认展开第一行
dialog.value.tableData.expands= [arr[0]];
hideDialog(true);
}
//编辑
let handleEdit = (flag,row) =>{
... ... @@ -126,24 +207,94 @@ export default {
}
}
}
//同步 todo
//同步
let handleRefresh = (flag,row) =>{
let ids=[];
let isAll=false;
if(flag==1){
//单个同步 row-->对象
ids.push(row.id);
isAll=true;
}else{
//多选同步 selectionData.value-->数组
if(selectionData.value.length>0){
//...
selectionData.value.map(item=>{
ids.push(item.id)
})
isAll=true;
}else{
proxy.$global.showMsg('请选择数据','warning')
isAll=false;
}
}
let idList='';
if(ids.length>0){
idList=ids.join(',');
}
let param={
resType:resType.value,
idList:idList
}
if(isAll){
proxy.$global.confirm('确认同步该资源类型"'+resTypeName.value +'"下的资源"'+idList+'"?', function () {
proxy.$http.get(`/api-web/cmdbSync/sync`, param, function (res) {
if (res && res.success) {
proxy.$global.showMsg('同步成功','success');
selectionData.value=[];
}else{
proxy.$global.showMsg('同步失败','error');
}
setData();
});
})
}else{
proxy.$global.confirm('确认同步该资源类型下所有资源?', function () {
proxy.$http.get(`/api-web/cmdbSync/sync`, param, function (res) {
if (res && res.success) {
proxy.$global.showMsg('同步成功','success');
selectionData.value=[];
}else{
proxy.$global.showMsg('同步失败','error');
}
setData();
});
})
}
}
//忽略
let handleIgnore=()=>{
//多选忽略 selectionData.value-->数组
if(selectionData.value.length>0){
let idList='';
let idArr=[]
selectionData.value.map(item=>{
idArr.push(item.id)
})
if(idArr.length>0){
idList=idArr.join(',')
}
proxy.$global.confirm('确认忽略该资源类型"'+resTypeName.value +'"下的资源"'+idList+'"?', function () {
proxy.$http.get(`/api-web/cmdbSync/ignore`, {idList:idList}, function (res) {
if (res && res.success) {
proxy.$global.showMsg('忽略成功','success');
selectionData.value=[];
}else{
proxy.$global.showMsg('忽略失败','error');
}
getDataList();
});
})
}else{
proxy.$global.showMsg('请选择数据','warning')
}
}
//编辑返回数据
let callbackedit=(obj)=>{
console.log("***",obj.editTbaleData,obj.visibility)
hideDialog(obj.visibility)
hideDialog(obj.visibility,true)
//obj.editTbaleData编辑后的数据,todo
// getDataList();//获取列表数据
}
... ... @@ -157,41 +308,73 @@ export default {
proxy.$http.post(`/api-web/attribute/getTree`, {}, function (res) {
if (res && res.data) {
treeData.value = res.data;
if( treeData.value && treeData.value.length>0){
expendKeys.value.push(treeData.value[0].id);
checkedKeys.value=treeData.value[0].children[0].id;
}
getDataList();//获取列表数据
}
});
}
// 获取列表 todo
// 获取列表
let getDataList = () => {
if(defaultNode.value){
if(defaultNode.value && treeData.value[0]){
resType.value=treeData.value[0].children[0].value;
resTypeName.value=treeData.value[0].children[0].title;
}
let params={
resType:resType.value,
pageNum: search.value.pageNum,
pageSize: search.value.pageSize,
keyword:search.value.keyword
page: search.value.pageNum,
limit: search.value.pageSize,
keyword:search.value.keyword,
provider:search.value.provider,//厂商
system:search.value.system,//系统 linux
resSyncState:search.value.resSyncState,//资源处理状态 0 监控同步成功
}
proxy.$http.post(`/api-web/`, params, function (res) {
if (res && res.object) {
tableData.value.dataList = res.object;
tableData.value.count = parseInt(res.object.total);
proxy.$http.get(`/api-web/cmdbSync/getPage`, params, function (res) {
if (res && res.data) {
tableData.value.dataList = res.data;
tableData.value.count = parseInt(res.count);
} else {
tableData.value.dataList = [];
tableData.value.count = 0;
}
});
}
//获取字典接口
let getDdicCode=(code)=>{
proxy.$http.post(`/api-web/manage/ddic/findSucDdics/`+code, {}, function (res) {
if (res && res.data) {
if(code == 'resSyncState'){
resSyncStateData.value=res.data;
}else if(code == 'provider'){
providerData.value=res.data;
}else if(code == 'os'){
systemData.value=res.data;
}
}
});
}
// 挂载完
Vue.onMounted(() => {
// getDataList();//获取列表数据
getResData();//获取资源树数据
setTimeout(function (){
proxy.$refs.datasyncTree.setCurrentKey(checkedKeys.value);
},350)
getDdicCode('resSyncState');
getDdicCode('provider');
getDdicCode('os');
})
return {
defaultProps,
treeData,
checkedKeys,
expendKeys,
defaultNode,
handleNodeClick,
getResData,
... ... @@ -199,6 +382,7 @@ export default {
search,
dialog,
hideDialog,
setData,
selectionChange,
selectionData,
handle,
... ... @@ -209,7 +393,13 @@ export default {
handleRefresh,
callbackedit,
goResDetail,
resType
resType,
resTypeName,
getDdicCode,
providerData,
systemData,
resSyncStateData,
handleIgnore
}
}
... ...
<div class="container" :style="{'height':height+'px','max-height':height+'px'}">
<div class="cm-card" :style="{'min-height':height+'px','max-height':height+'px','height':'100%','padding-top':'3px'}">
<div class="ping-detail">
<el-descriptions
class=""
title=""
:column="2"
:size="size"
border
>
<el-descriptions-item>
<template #label>
<div class="cell-item">
资源名称
</div>
</template>
{{detail.resName}}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">
IP地址
</div>
</template>
{{detail.ip}}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">
资源类型
</div>
</template>
{{detail.resTypeName}}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">
责任人
</div>
</template>
{{detail.adminName}}
</el-descriptions-item>
</el-descriptions>
</div>
<div class="search">
<div class="condition">
<el-form-item >
<el-input v-model="search.keyword" placeholder="=资源名称、日志内容="></el-input>
</el-form-item>
<el-form-item >
<el-select v-model="search.kpiId" class="m-2" placeholder="指标" clearable @change="kpiChange">
<el-option
v-for="item in kpiData"
:key="item.ddicCode"
:label="item.ddicName"
:value="item.ddicCode"
/>
</el-select>
</el-form-item>
<el-form-item >
<el-select v-model="search.flag" class="m-2" placeholder="flag" clearable>
<el-option
v-for="item in flagData"
:key="item.ddicCode"
:label="item.ddicName"
:value="item.ddicCode"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-date-picker
v-model="search.dateTime"
type="date"
placeholder="日期"
end-placeholder="结束时间"
value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item >
<el-button @click="getDataList">查询</el-button>
</el-form-item>
</div>
</div>
<div class="search-table">
<cm-table-page :columns="tableData.columns" :dataList="tableData.dataList"
:showIndex="true"
:total="tableData.count"
@loaddata = "loaddata"
:showSelection="false"
:showBorder="true"
:loading="false"
:pageSize="search.pageSize"
:showPage="true"
:showTools="true"
:height="height - 110">
<template #default="{row,prop,column}">
<!--<div v-if="prop == 'message'" >
<el-tooltip >
<template #content>
<div style="max-width:400px;overflow: hidden; text-overflow: ellipsis;display: -webkit-box; -webkit-line-clamp: 5; -webkit-box-orient: vertical;">
{{row.message}}
</div>
</template>
<div v-html="row.message" style="overflow: hidden; text-overflow: ellipsis;display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical;"></div>
</el-tooltip>
</div>-->
</template>
<template #tools="{scope}">
<div class="list-handle">
<span class="icon-bg">
<i class="el-icon-view" title="查看" @click="handleView(scope.row)"></i>
</span>
</div>
</template>
</cm-table-page>
</div>
</div>
</div>
<!--弹框-->
<cm-dialog :title="dialog.title" width="60%" :showDialogVisible="dialog.show" @hidedialog="hideDialog" :showFooter="false">
<template v-slot>
<pingDetail :detail="dialog.detail" />
</template>
</cm-dialog>
... ...
export default {
name: 'pingIndex',
template: '',
components: {
'pingDetail': Vue.defineAsyncComponent(
() => myImport('views/ping/pingDetail/index')
)
},
props: [],
setup(props, {attrs, slots, emit}) {
const {proxy} = Vue.getCurrentInstance();
let height = Vue.ref(window.innerHeight);
let resId=Vue.ref('');
let dateTime=Vue.ref([]);
let kpiIdent=Vue.ref('');
let search = Vue.ref({
kpiId:'',
sortBy:'dbTime',
scopeBy:'dbTimeStr.keyword',
keyword: '',
type:'syslog',
pageNum: 1,
pageSize: 20,
dateTime:[],
resType:'',
});
let dialog = Vue.ref({
title : "ping详情",
show:false,
esId : ''
});
//表格字段
let tableData = Vue.ref({
count:0,
dataList: [],
columns: [
{
prop: 'collTime',
label: '采集时间',
sortable: true,
align: 'center',
width: '250',
},
{
prop: 'dbTime',
label: '入库时间',
sortable: true,
align: 'center',
width: '250'
},
{
prop: 'kpiValue',
label: '采集值',
sortable: true,
align: 'center',
width: '200'
},
{
prop: 'taskName',
label: '采集任务',
sortable: true,
align: 'center',
width: '200'
},
{
prop: 'templateName',
label: '采集模板',
sortable: true,
align: 'center',
width: '200'
},
{
prop: 'directiveName',
label: '指令名称',
sortable: true,
align: 'center',
width: '200'
}, {
prop: 'ext',
label: '扩展信息',
sortable: true,
align: 'center',
width: '200',
render:function (row){
return `<pre>${row.ext}</pre>`
}
}, {
prop: 'message',
label: '异常信息',
sortable: true,
align: 'center',
render:function (row){
return `<pre>${row.message}</pre>`
}
}
]
})
let resTypeArr = Vue.ref([]);
let getResType = (arr) => {
var types = arr.map(function (v) {
return v.id;
});
resTypeArr.value = types;
search.value.resType=resTypeArr.value.join(',');
// getDataList();
}
//获取时间点 转年月日的方法
const getDateTime=(newDate)=>{
let dateTime='';
let year=newDate.getFullYear();//获取当前年
let month1=(newDate.getMonth()+1)+'';
let month=timeFormat(month1);//获取当前月
let day=timeFormat(newDate.getDate());//获取当前日
let hours=timeFormat(newDate.getHours()+'');//获取当前时
let minutes=timeFormat(newDate.getMinutes()+'');//获取当前分
let seconds=timeFormat(newDate.getSeconds()+'');//获取当前秒
dateTime= year+'-'+month+'-'+day;//' '+hours+':'+minutes+':'+seconds;
return dateTime;
}
//转换个位数为 00
let timeFormat =(number)=> {
return number.length == 1 ? ('0' + number) : number
}
// 获取列表
let getDataList = () => {
let nowDate=getDateTime(new Date());
let dateStr='';
if(kpiIdent.value==1){
dateStr='monitor-performance_';
}else{
dateStr='monitor-collector_';
}
if(search.value.dateTime){
dateStr+=search.value.dateTime;
}else {
dateStr+=nowDate;
}
let params={
resId:resId.value,
kpiId:search.value.kpiId,
flag:search.value.flag,
indexName:dateStr,
pageNum: search.value.pageNum,
pageSize: search.value.pageSize,
type:search.value.type,
sortBy:search.value.sortBy,
scopeBy:search.value.scopeBy,
resType:search.value.resType,
param:{}
}
if(search.value.keyword){
params.param={
'resName.keyword': search.value.keyword,
'host.keyword':search.value.keyword,
'message.keyword':search.value.keyword,
}
}
if(search.value.kpiId){
params['param']['kpiId.keyword']=search.value.kpiId;
}
proxy.$http.post(`/api-web/esData/list`, params, function (res) {
if (res && res.object) {
let dataList=res.object.content;
let arr=[];
dataList.map(item=>{
arr.push(item[0])
})
tableData.value.dataList = arr;
tableData.value.count = parseInt(res.object.total);
} else {
tableData.value.dataList = [];
tableData.value.count = 0;
}
});
}
let loaddata = ({page, limit}) => {
search.value.pageNum = page;
search.value.pageSize = limit;
getDataList();
}
let hideDialog = (flg) => {
dialog.value.show = flg;
}
// 处理弹框
let handle = (row) =>{
hideDialog(true);
dialog.value.detail = row;
}
//查看详情
let handleView = (row) =>{
handle(row);
}
//查看资源详情
let goResDetail=(resId,resName,resType)=>{
proxy.$global.openDetail(resId, resType, proxy);
}
//指标数据
let kpiData=Vue.ref([]);
let getKpiData=()=>{
proxy.$http.post(`/api-web/manage/ddic/findSucDdics/LOG_SOURCE_TYPE`, {}, function (res) {
if (res && res.data) {
kpiData.value = res.data;
}
});
}
//flag数据
let flagData=Vue.ref([]);
let getFlagData=()=>{
proxy.$http.post(`/api-web/manage/ddic/findSucDdics/LOG_SOURCE_TYPE?kpiId=`+search.kpiId+'&resId='+resId.value, {}, function (res) {
if (res && res.data) {
flagData.value = res.data;
}
});
}
//指标改变事件
let kpiChange=(val)=>{
getFlagData();
}
let detail=Vue.ref({})
//获取resId
let getResId=()=>{
detail.value=proxy.$route.query;
resId.value=proxy.$route.query.resId;
}
// 挂载完
Vue.onMounted(() => {
getResId();
getDataList();
getKpiData();
})
return {
resId,
getResId,
detail,
kpiData,
kpiIdent,
getKpiData,
flagData,
getFlagData,
kpiChange,
dateTime,
height,
search,
dialog,
hideDialog,
handle,
loaddata,
tableData,
getDataList,
resTypeArr,
getResType,
handleView,
goResDetail,
getDateTime
}
}
}
... ...
<div class="esData-detail-container">
<el-descriptions
class=""
title="日志信息"
:column="2"
:size="size"
border
>
<el-descriptions-item>
<template #label>
<div class="cell-item">
资源名称
</div>
</template>
{{detail.resName}}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">
IP地址
</div>
</template>
{{detail.host}}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">
资源类型
</div>
</template>
{{detail.resTypeName}}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">
日志来源
</div>
</template>
{{detail.type}}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">
日志类型
</div>
</template>
{{detail.program}}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">
采集时间
</div>
</template>
{{detail.dbTimeStr}}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">
日志时间
</div>
</template>
{{detail.logDate}}
</el-descriptions-item>
</el-descriptions>
<div class="info-title">
<span style="font-weight:bold">日志内容</span>
</div>
<div class="esData-detail-info-content" v-html="detail.message">
</div>
</div>
\ No newline at end of file
... ...
export default {
name: 'esDataDetail',
template: '',
components: {
},
props: {
detail:{
type:Object,
default: {}
}
},
setup(props, {attrs, slots, emit}) {
const {proxy} = Vue.getCurrentInstance();
// 挂载完
Vue.onMounted(() => {
})
return {
}
}
}
... ...
... ... @@ -204,6 +204,18 @@ const routes = [{
name: 'esDataIndex',
component: () => myImport('views/esData/index'),
},
//监控对接CMDB功能
{
path: '/cmdbdatasync',
name: 'cmdbdatasync',
component: () => myImport('views/cmdbdatasync/index'),
},
//ping详情列表
{
path: '/ping',
name: 'pingIndex',
component: () => myImport('views/ping/index'),
},
];
// hash模式: createWebHashHistory
... ...