Authored by 王涛

Merge branch 'master-500-dev-lushangqing' into 'master-500-dev'

cmdb数据同步页列表无数据时调整,ping详情页列表静态页面搭建 #1



See merge request !569
@@ -3204,6 +3204,7 @@ layui.define(['laytpl', 'admin', 'form', 'table', 'echarts', 'sessions', 'xmSele @@ -3204,6 +3204,7 @@ layui.define(['laytpl', 'admin', 'form', 'table', 'echarts', 'sessions', 'xmSele
3204 } 3204 }
3205 title += `<a class="layui-icon filterList" data-id=${resId} lay-tips="指标过滤清单" style="margin-left: 10px"><i class="iconfont">&#XE516;</i></a>`; 3205 title += `<a class="layui-icon filterList" data-id=${resId} lay-tips="指标过滤清单" style="margin-left: 10px"><i class="iconfont">&#XE516;</i></a>`;
3206 title += `<a class="layui-icon res-view-relation-topo" data-id=${resId} lay-tips="查看资源关系拓扑" style="margin-left: 10px"><i class="iconfont">&#XE515;</i></a>`; 3206 title += `<a class="layui-icon res-view-relation-topo" data-id=${resId} lay-tips="查看资源关系拓扑" style="margin-left: 10px"><i class="iconfont">&#XE515;</i></a>`;
  3207 + 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>`;
3207 if (resCategory === 'share' && hardwareFlag.endsWith("Y")) { 3208 if (resCategory === 'share' && hardwareFlag.endsWith("Y")) {
3208 /* 3209 /*
3209 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>`; 3210 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 @@ -3494,6 +3495,28 @@ layui.define(['laytpl', 'admin', 'form', 'table', 'echarts', 'sessions', 'xmSele
3494 } 3495 }
3495 common.viewResTopo($(this).data('id')); 3496 common.viewResTopo($(this).data('id'));
3496 }); 3497 });
  3498 + //start 查看ping详情列表页 lsq 2022-04-24
  3499 + $('a.res-view-ping').unbind('click').on('click', function () {
  3500 + // if ($.inArray('back:details:viewtopo', checkList) === -1) {
  3501 + // layer.msg('暂无权限!', {icon: 0});
  3502 + // return;
  3503 + // }
  3504 + let paramStr='?resId='+$(this).data('id')+'&resName='+$(this).data('resName')+'&resTypeName='+$(this).data('resTypeName')+'&adminName='+$(this).data('adminName')+'&ip='+$(this).data('ip')
  3505 +
  3506 + layer.open({
  3507 + title: ['ping详情', 'font-size:18px;'],
  3508 + type: 2,
  3509 + area: ['80%', '90%'],
  3510 + shadeClose: true,//开启遮罩层
  3511 + id: 'res-ping',
  3512 + // content: laytpl(res.body).render(JSON.stringify(params)),
  3513 + content: ['/vue3/index.html#/ping'+paramStr, 'no'],
  3514 + cancel: function () {
  3515 + clearTimeout();
  3516 + }
  3517 + });
  3518 + });
  3519 + //end lsq 2022-04-24
3497 3520
3498 // 查看资产配置信息 3521 // 查看资产配置信息
3499 $('a.res-view-assets-details').unbind('click').on('click', function () { 3522 $('a.res-view-assets-details').unbind('click').on('click', function () {
@@ -115,6 +115,12 @@ const routes = [{ @@ -115,6 +115,12 @@ const routes = [{
115 name: 'cmdbdatasync', 115 name: 'cmdbdatasync',
116 component: () => myImport('views/cmdbdatasync/index'), 116 component: () => myImport('views/cmdbdatasync/index'),
117 }, 117 },
  118 + //ping详情列表
  119 + {
  120 + path: '/ping',
  121 + name: 'pingIndex',
  122 + component: () => myImport('views/ping/index'),
  123 + },
118 ]; 124 ];
119 125
120 // hash模式: createWebHashHistory 126 // hash模式: createWebHashHistory
@@ -39,10 +39,13 @@ export default { @@ -39,10 +39,13 @@ export default {
39 let data=editTbaleData.value; 39 let data=editTbaleData.value;
40 let arr=[]; 40 let arr=[];
41 data.map(item=>{ 41 data.map(item=>{
42 - item.proto.map(item=>{  
43 - item.paramValue=item.defaultValue;  
44 - item.protocol=item.protocolId;  
45 - }) 42 + if(item.proto && item.proto.length>0){
  43 + item.proto.map(item=>{
  44 + item.paramValue=item.defaultValue;
  45 + item.protocol=item.protocolId;
  46 + })
  47 + }
  48 +
46 arr.push({ 49 arr.push({
47 bean:item, 50 bean:item,
48 proto:item.proto 51 proto:item.proto
@@ -55,7 +55,7 @@ @@ -55,7 +55,7 @@
55 </div> 55 </div>
56 </div> 56 </div>
57 <div class="search-table"> 57 <div class="search-table">
58 - <cm-table-page v-if="tableData.dataList && tableData.dataList.length>0" :columns="tableData.columns" :dataList="tableData.dataList" 58 + <cm-table-page v-if="tableData.dataList " :columns="tableData.columns" :dataList="tableData.dataList"
59 :showIndex="true" 59 :showIndex="true"
60 :total="tableData.count" 60 :total="tableData.count"
61 @loaddata = "loaddata" 61 @loaddata = "loaddata"
  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="ping-detail">
  4 + <el-descriptions
  5 + class=""
  6 + title=""
  7 + :column="2"
  8 + :size="size"
  9 + border
  10 + >
  11 + <el-descriptions-item>
  12 + <template #label>
  13 + <div class="cell-item">
  14 + 资源名称
  15 + </div>
  16 + </template>
  17 + {{detail.resName}}
  18 + </el-descriptions-item>
  19 + <el-descriptions-item>
  20 + <template #label>
  21 + <div class="cell-item">
  22 + IP地址
  23 + </div>
  24 + </template>
  25 + {{detail.ip}}
  26 + </el-descriptions-item>
  27 + <el-descriptions-item>
  28 + <template #label>
  29 + <div class="cell-item">
  30 + 资源类型
  31 + </div>
  32 + </template>
  33 + {{detail.resTypeName}}
  34 + </el-descriptions-item>
  35 + <el-descriptions-item>
  36 + <template #label>
  37 + <div class="cell-item">
  38 + 责任人
  39 + </div>
  40 + </template>
  41 + {{detail.adminName}}
  42 + </el-descriptions-item>
  43 + </el-descriptions>
  44 + </div>
  45 + <div class="search">
  46 + <div class="condition">
  47 + <el-form-item >
  48 + <el-input v-model="search.keyword" placeholder="=资源名称、日志内容="></el-input>
  49 + </el-form-item>
  50 + <el-form-item >
  51 + <el-select v-model="search.kpiId" class="m-2" placeholder="指标" clearable @change="kpiChange">
  52 + <el-option
  53 + v-for="item in kpiData"
  54 + :key="item.ddicCode"
  55 + :label="item.ddicName"
  56 + :value="item.ddicCode"
  57 +
  58 + />
  59 + </el-select>
  60 + </el-form-item>
  61 + <el-form-item >
  62 + <el-select v-model="search.flag" class="m-2" placeholder="flag" clearable>
  63 + <el-option
  64 + v-for="item in flagData"
  65 + :key="item.ddicCode"
  66 + :label="item.ddicName"
  67 + :value="item.ddicCode"
  68 + />
  69 + </el-select>
  70 + </el-form-item>
  71 +
  72 + <el-form-item>
  73 + <el-date-picker
  74 + v-model="search.dateTime"
  75 + type="date"
  76 + placeholder="日期"
  77 + end-placeholder="结束时间"
  78 + value-format="YYYY-MM-DD"
  79 + />
  80 +
  81 + </el-form-item>
  82 + <el-form-item >
  83 + <el-button @click="getDataList">查询</el-button>
  84 + </el-form-item>
  85 + </div>
  86 + </div>
  87 +
  88 + <div class="search-table">
  89 + <cm-table-page :columns="tableData.columns" :dataList="tableData.dataList"
  90 + :showIndex="true"
  91 + :total="tableData.count"
  92 + @loaddata = "loaddata"
  93 + :showSelection="false"
  94 + :showBorder="true"
  95 + :loading="false"
  96 + :pageSize="search.pageSize"
  97 + :showPage="true"
  98 + :showTools="true"
  99 + :height="height - 110">
  100 + <template #default="{row,prop,column}">
  101 + <!--<div v-if="prop == 'message'" >
  102 + <el-tooltip >
  103 + <template #content>
  104 + <div style="max-width:400px;overflow: hidden; text-overflow: ellipsis;display: -webkit-box; -webkit-line-clamp: 5; -webkit-box-orient: vertical;">
  105 + {{row.message}}
  106 + </div>
  107 + </template>
  108 + <div v-html="row.message" style="overflow: hidden; text-overflow: ellipsis;display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical;"></div>
  109 + </el-tooltip>
  110 + </div>-->
  111 + </template>
  112 + <template #tools="{scope}">
  113 + <div class="list-handle">
  114 + <span class="icon-bg">
  115 + <i class="el-icon-view" title="查看" @click="handleView(scope.row)"></i>
  116 + </span>
  117 + </div>
  118 + </template>
  119 + </cm-table-page>
  120 + </div>
  121 + </div>
  122 +</div>
  123 +
  124 +<!--弹框-->
  125 +<cm-dialog :title="dialog.title" width="60%" :showDialogVisible="dialog.show" @hidedialog="hideDialog" :showFooter="false">
  126 + <template v-slot>
  127 + <pingDetail :detail="dialog.detail" />
  128 + </template>
  129 +</cm-dialog>
  130 +
  1 +export default {
  2 + name: 'pingIndex',
  3 + template: '',
  4 + components: {
  5 + 'pingDetail': Vue.defineAsyncComponent(
  6 + () => myImport('views/ping/pingDetail/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 resId=Vue.ref('');
  14 + let dateTime=Vue.ref([]);
  15 + let kpiIdent=Vue.ref('');
  16 + let search = Vue.ref({
  17 + kpiId:'',
  18 + sortBy:'dbTime',
  19 + scopeBy:'dbTimeStr.keyword',
  20 + keyword: '',
  21 + type:'syslog',
  22 + pageNum: 1,
  23 + pageSize: 20,
  24 + dateTime:[],
  25 + resType:'',
  26 + });
  27 + let dialog = Vue.ref({
  28 + title : "ping详情",
  29 + show:false,
  30 + esId : ''
  31 + });
  32 + //表格字段
  33 + let tableData = Vue.ref({
  34 + count:0,
  35 + dataList: [],
  36 + columns: [
  37 + {
  38 + prop: 'collTime',
  39 + label: '采集时间',
  40 + sortable: true,
  41 + align: 'center',
  42 + width: '250',
  43 + },
  44 + {
  45 + prop: 'dbTime',
  46 + label: '入库时间',
  47 + sortable: true,
  48 + align: 'center',
  49 + width: '250'
  50 + },
  51 + {
  52 + prop: 'kpiValue',
  53 + label: '采集值',
  54 + sortable: true,
  55 + align: 'center',
  56 + width: '200'
  57 + },
  58 + {
  59 + prop: 'taskName',
  60 + label: '采集任务',
  61 + sortable: true,
  62 + align: 'center',
  63 + width: '200'
  64 + },
  65 + {
  66 + prop: 'templateName',
  67 + label: '采集模板',
  68 + sortable: true,
  69 + align: 'center',
  70 + width: '200'
  71 + },
  72 + {
  73 + prop: 'directiveName',
  74 + label: '指令名称',
  75 + sortable: true,
  76 + align: 'center',
  77 + width: '200'
  78 + }, {
  79 + prop: 'ext',
  80 + label: '扩展信息',
  81 + sortable: true,
  82 + align: 'center',
  83 + width: '200',
  84 + render:function (row){
  85 + return `<pre>${row.ext}</pre>`
  86 + }
  87 + }, {
  88 + prop: 'message',
  89 + label: '异常信息',
  90 + sortable: true,
  91 + align: 'center',
  92 + render:function (row){
  93 + return `<pre>${row.message}</pre>`
  94 + }
  95 + }
  96 + ]
  97 + })
  98 + let resTypeArr = Vue.ref([]);
  99 + let getResType = (arr) => {
  100 + var types = arr.map(function (v) {
  101 + return v.id;
  102 + });
  103 + resTypeArr.value = types;
  104 + search.value.resType=resTypeArr.value.join(',');
  105 + // getDataList();
  106 + }
  107 + //获取时间点 转年月日的方法
  108 + const getDateTime=(newDate)=>{
  109 + let dateTime='';
  110 + let year=newDate.getFullYear();//获取当前年
  111 + let month1=(newDate.getMonth()+1)+'';
  112 + let month=timeFormat(month1);//获取当前月
  113 + let day=timeFormat(newDate.getDate());//获取当前日
  114 + let hours=timeFormat(newDate.getHours()+'');//获取当前时
  115 + let minutes=timeFormat(newDate.getMinutes()+'');//获取当前分
  116 + let seconds=timeFormat(newDate.getSeconds()+'');//获取当前秒
  117 + dateTime= year+'-'+month+'-'+day;//' '+hours+':'+minutes+':'+seconds;
  118 + return dateTime;
  119 + }
  120 + //转换个位数为 00
  121 + let timeFormat =(number)=> {
  122 + return number.length == 1 ? ('0' + number) : number
  123 + }
  124 + // 获取列表
  125 + let getDataList = () => {
  126 + let nowDate=getDateTime(new Date());
  127 + let dateStr='';
  128 + if(kpiIdent.value==1){
  129 + dateStr='monitor-performance_';
  130 + }else{
  131 + dateStr='monitor-collector_';
  132 + }
  133 + if(search.value.dateTime){
  134 + dateStr+=search.value.dateTime;
  135 + }else {
  136 + dateStr+=nowDate;
  137 + }
  138 +
  139 + let params={
  140 + resId:resId.value,
  141 + kpiId:search.value.kpiId,
  142 + flag:search.value.flag,
  143 + indexName:dateStr,
  144 + pageNum: search.value.pageNum,
  145 + pageSize: search.value.pageSize,
  146 + type:search.value.type,
  147 + sortBy:search.value.sortBy,
  148 + scopeBy:search.value.scopeBy,
  149 + resType:search.value.resType,
  150 + param:{}
  151 + }
  152 + if(search.value.keyword){
  153 + params.param={
  154 + 'resName.keyword': search.value.keyword,
  155 + 'host.keyword':search.value.keyword,
  156 + 'message.keyword':search.value.keyword,
  157 + }
  158 + }
  159 + if(search.value.kpiId){
  160 + params['param']['kpiId.keyword']=search.value.kpiId;
  161 + }
  162 + proxy.$http.post(`/api-web/esData/list`, params, function (res) {
  163 + if (res && res.object) {
  164 + let dataList=res.object.content;
  165 + let arr=[];
  166 + dataList.map(item=>{
  167 + arr.push(item[0])
  168 + })
  169 + tableData.value.dataList = arr;
  170 + tableData.value.count = parseInt(res.object.total);
  171 + } else {
  172 + tableData.value.dataList = [];
  173 + tableData.value.count = 0;
  174 + }
  175 + });
  176 + }
  177 +
  178 + let loaddata = ({page, limit}) => {
  179 + search.value.pageNum = page;
  180 + search.value.pageSize = limit;
  181 + getDataList();
  182 + }
  183 +
  184 + let hideDialog = (flg) => {
  185 + dialog.value.show = flg;
  186 + }
  187 +
  188 + // 处理弹框
  189 + let handle = (row) =>{
  190 + hideDialog(true);
  191 + dialog.value.detail = row;
  192 + }
  193 +
  194 + //查看详情
  195 + let handleView = (row) =>{
  196 + handle(row);
  197 + }
  198 + //查看资源详情
  199 + let goResDetail=(resId,resName,resType)=>{
  200 + proxy.$global.openDetail(resId, resType, proxy);
  201 +
  202 + }
  203 + //指标数据
  204 + let kpiData=Vue.ref([]);
  205 + let getKpiData=()=>{
  206 + proxy.$http.post(`/api-web/manage/ddic/findSucDdics/LOG_SOURCE_TYPE`, {}, function (res) {
  207 + if (res && res.data) {
  208 + kpiData.value = res.data;
  209 + }
  210 + });
  211 + }
  212 + //flag数据
  213 + let flagData=Vue.ref([]);
  214 + let getFlagData=()=>{
  215 + proxy.$http.post(`/api-web/manage/ddic/findSucDdics/LOG_SOURCE_TYPE?kpiId=`+search.kpiId+'&resId='+resId.value, {}, function (res) {
  216 + if (res && res.data) {
  217 + flagData.value = res.data;
  218 + }
  219 + });
  220 + }
  221 + //指标改变事件
  222 + let kpiChange=(val)=>{
  223 + getFlagData();
  224 + }
  225 + let detail=Vue.ref({})
  226 + //获取resId
  227 + let getResId=()=>{
  228 + detail.value=proxy.$route.query;
  229 + resId.value=proxy.$route.query.resId;
  230 +
  231 + }
  232 + // 挂载完
  233 + Vue.onMounted(() => {
  234 + getResId();
  235 + getDataList();
  236 + getKpiData();
  237 + })
  238 +
  239 +
  240 + return {
  241 + resId,
  242 + getResId,
  243 + detail,
  244 + kpiData,
  245 + kpiIdent,
  246 + getKpiData,
  247 + flagData,
  248 + getFlagData,
  249 + kpiChange,
  250 + dateTime,
  251 + height,
  252 + search,
  253 + dialog,
  254 + hideDialog,
  255 + handle,
  256 + loaddata,
  257 + tableData,
  258 + getDataList,
  259 + resTypeArr,
  260 + getResType,
  261 + handleView,
  262 + goResDetail,
  263 + getDateTime
  264 + }
  265 + }
  266 +
  267 +}
  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>
  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 +}
@@ -210,6 +210,12 @@ const routes = [{ @@ -210,6 +210,12 @@ const routes = [{
210 name: 'cmdbdatasync', 210 name: 'cmdbdatasync',
211 component: () => myImport('views/cmdbdatasync/index'), 211 component: () => myImport('views/cmdbdatasync/index'),
212 }, 212 },
  213 + //ping详情列表
  214 + {
  215 + path: '/ping',
  216 + name: 'pingIndex',
  217 + component: () => myImport('views/ping/index'),
  218 + },
213 ]; 219 ];
214 220
215 // hash模式: createWebHashHistory 221 // hash模式: createWebHashHistory