Compare commits

...

1 Commits

Author SHA1 Message Date
TangShan_DD 992953331a fix: cloundTower代码迁移 2024-05-28 15:52:46 +08:00
37 changed files with 2583 additions and 19 deletions

View File

@ -110,6 +110,8 @@ export function resourceTypeMonitorFilter(value) {
MONITOR_HUAWEI_VM: '华为云ECS',
MONITOR_SMARTX_VM: 'SMARTX云主机',
MONITOR_SMARTX_HOST: 'SMARTX宿主机',
MONITOR_CLOUDTOWER_HOST: 'CloudTower宿主机',
MONITOR_CLOUDTOWER_VM: 'CloudTower云主机',
MONITOR_STORAGE_DELL_STORAGE: 'Dell存储设备',
MONITOR_STORAGE_DELL_DISK: 'Dell磁盘',
MONITOR_STORAGE_DELL_VOLUME: 'Dell存储卷',

View File

@ -18,6 +18,8 @@ const monitor = {
MonitorCloudHuawei: () => import('views/compute/cloud/huawei/index.vue'), // 华为云
MonitorCloudH3C: () => import('views/compute/cloud/h3c/index.vue'), // 华三云
MonitorCloudSmart: () => import('views/compute/cloud/smart/index.vue'), // smartx
MonitorCloudCloudTower: () => import('views/compute/cloud/cloudTower/index.vue'), // cloudtower
MonitorContainerDetail: () => import('views/compute/cloud/vcenter/platformMonitorDetail.vue'), // 告警详情
MonitorDetailList: () => import('views/compute/cloud/vcenter/platformMonitorDetail.vue'), // 告警详情
MonitorFocusList: () => import('views/storage/huawei/list.vue'), // 集中式存储列表
@ -43,6 +45,9 @@ const monitor = {
mOneVmMonitor: () => import('views/compute/cloud/platformMonitor/manageone_vm.vue'),
SmartxServerMonitor: () => import('views/compute/cloud/platformMonitor/smartx_host.vue'),
SmartxVmMonitor: () => import('views/compute/cloud/platformMonitor/smartx_vm.vue'),
CloudTowerServerMonitor: () => import('views/compute/cloud/platformMonitor/cloudTower_host.vue'),
CloudTowerVmMonitor: () => import('views/compute/cloud/platformMonitor/cloudTower_vm.vue'),
VmMonitor: () => import('views/compute/cloud/platformMonitor/cloudTower_vm.vue'),
monitorDatabaseDetail: () => import('views/compute/cloud/vcenter/platformMonitorDetail.vue'),
huaweiStorageList: () => import('views/storage/huawei/list.vue'),
// 新添加的数据库监控组件

View File

@ -314,3 +314,10 @@ export function getSmartHosts(params) {
params: params
})
}
// 主机详情
export function getHostDetail(id, vendorType) {
return request.get(`/cms/v1/hosts/${id}`, {
params: wrapperParams({ type: vendorType })
})
}

View File

@ -163,7 +163,7 @@ export default {
label: '所属平台',
value: 'vendorId',
data: [],
service: { api: conditionCloudVendor, params: { condition: JSON.stringify({ condition: 'listByTypes', types: ['OPENSTACK', 'VMWARE', 'FUSIONCLOUD', 'HMC', 'MANAGEONE', 'KUBERNETES', 'TIANYI', 'HUAWEI', 'H3C', 'ALIYUN', 'SMARTX'] }) }, attr: 'data' }
service: { api: conditionCloudVendor, params: { condition: JSON.stringify({ condition: 'listByTypes', types: ['OPENSTACK', 'VMWARE', 'FUSIONCLOUD', 'HMC', 'MANAGEONE', 'KUBERNETES', 'TIANYI', 'HUAWEI', 'H3C', 'ALIYUN', 'SMARTX', 'CLOUDTOWER'] }) }, attr: 'data' }
},
{ type: 'Select', label: '告警级别', value: 'level', data: alarmLevelData, props: { value: 'value' } },
{ type: 'DateRange', value: 'gmtTrigger', label: '' },

View File

@ -147,7 +147,7 @@ export default {
label: '所属平台',
value: 'vendorId',
data: [],
service: { api: conditionCloudVendor, params: { condition: JSON.stringify({ condition: 'listByTypes', types: ['OPENSTACK', 'VMWARE', 'FUSIONCLOUD', 'HMC', 'MANAGEONE', 'KUBERNETES', 'TIANYI', 'HUAWEI', 'H3C', 'ALIYUN', 'SMARTX'] }) }, attr: 'data' }
service: { api: conditionCloudVendor, params: { condition: JSON.stringify({ condition: 'listByTypes', types: ['OPENSTACK', 'VMWARE', 'FUSIONCLOUD', 'HMC', 'MANAGEONE', 'KUBERNETES', 'TIANYI', 'HUAWEI', 'H3C', 'ALIYUN', 'SMARTX', 'CLOUDTOWER'] }) }, attr: 'data' }
},
{ type: 'Select', label: '告警级别', value: 'level', data: alarmLevelData, props: { value: 'value' } },
{ type: 'DateRange', value: 'gmtTrigger', label: '' },

View File

@ -434,7 +434,14 @@ export default {
this.type = ''
this.activeName = 'list'
this.detailData = Object.assign({}, row)
if (this.detailData.resourceType == 'MONITOR_VCENTER_HOST' || this.detailData.resourceType == 'MONITOR_OPENSTACK_HOST' || this.detailData.resourceType == 'MONITOR_FUSIONCLOUD_HOST' || this.detailData.resourceType == 'MONITOR_H3C_HOST' || this.detailData.resourceType == 'MONITOR_SMARTX_HOST') {
if (
this.detailData.resourceType == 'MONITOR_VCENTER_HOST' ||
this.detailData.resourceType == 'MONITOR_OPENSTACK_HOST' ||
this.detailData.resourceType == 'MONITOR_FUSIONCLOUD_HOST' ||
this.detailData.resourceType == 'MONITOR_H3C_HOST' ||
this.detailData.resourceType == 'MONITOR_SMARTX_HOST' ||
this.detailData.resourceType == 'MONITOR_CLOUDTOWER_HOST'
) {
this.type = 'HOST'
}
const arr = []

View File

@ -16,6 +16,9 @@
<div v-else-if="record.vendorType == 'JDCLOUD'">
<div v-for="(item, index) in record.privateIpsList" :key="index">(){{ item }}</div>
</div>
<div v-else-if="record.vendorType == 'SMARTX' || record.vendorType == 'CLOUDTOWER'">
<div>{{ record.managerIp ? '(内网)' + record.managerIp : '--' }}</div>
</div>
<div v-else>
<div v-for="(item, index) in record.privateIpsList" :key="index">(){{ item }}</div>
</div>
@ -109,7 +112,7 @@ export default {
{ type: 'Select', label: '所属平台', value: 'vendorId', data: [], service: { api: getCloudVendor, params: { simple: true, params: this.$tools.handleSearchParam({ type: getVendorType(this.resourceType) }) }, attr: 'data.rows' } },
{ type: 'Const', value: 'vendorType', initValue: getVendorType(this.resourceType) },
{ type: 'Const', value: 'id', initValue: this.resourceIds && this.status == 'detail' ? this.resourceIds.join(',') : '', sign: 'IN' },
{ type: 'Const', value: 'isTemplate', initValue: getVendorType(this.resourceType) == 'VMWARE' || getVendorType(this.resourceType) == 'H3C' || getVendorType(this.resourceType) == 'SMARTX' ? false : '' }
{ type: 'Const', value: 'isTemplate', initValue: getVendorType(this.resourceType) == 'VMWARE' || getVendorType(this.resourceType) == 'H3C' || getVendorType(this.resourceType) == 'SMARTX' || getVendorType(this.resourceType) == 'CLOUDTOWER' ? false : '' }
],
list: [],
total: 0,

View File

@ -46,7 +46,7 @@ export default defineComponent({
const data = await conditionCloudVendor({
condition: JSON.stringify({
condition: 'listByTypes',
types: ['OPENSTACK', 'VMWARE', 'SMARTX']
types: ['OPENSTACK', 'VMWARE', 'SMARTX', 'CLOUDTOWER']
})
})
if (data.success) {
@ -62,7 +62,13 @@ export default defineComponent({
async function getCountData(vendorId: number) {
const res = await getPortal({ vendorId, code: 'resUsed' })
if (res.success) {
countData.value = res.data
const vendorType = unref(vendorList).find(({ id }) => id === vendorId).type
countData.value = res.data.filter((item) => {
if (['CLOUDTOWER', 'INSPURRAIL', 'FUSIONSPHERE'].includes(vendorType)) {
if (item.name === '磁盘') return false
}
return true
})
}
}
return {

View File

@ -57,7 +57,7 @@ export default {
const data = await conditionCloudVendor({
condition: JSON.stringify({
condition: 'listByTypes',
types: ['OPENSTACK', 'VMWARE', 'SMARTX']
types: ['OPENSTACK', 'VMWARE', 'SMARTX', 'CLOUDTOWER']
})
})
if (data.success) {

View File

@ -322,7 +322,12 @@ export default {
vendor: this.vendorType
}).then((data) => {
if (data.success) {
this.resUsedData = data.data
this.resUsedData = data.data.filter((item) => {
if (['CLOUDTOWER', 'INSPURRAIL', 'FUSIONSPHERE'].includes(this.vendorType)) {
if (item.name === '磁盘') return false
}
return true
})
this.detailData.cpuTotal = data.data[0].total
this.detailData.memTotal = data.data[1].total
this.detailData.diskTotal = data.data[2].total

View File

@ -368,7 +368,13 @@ export default {
},
getDetail(row) {
this.detailData = Object.assign({}, row)
if (this.detailData.resourceType == 'MONITOR_VCENTER_HOST' || this.detailData.resourceType == 'MONITOR_OPENSTACK_HOST' || this.detailData.resourceType == 'MONITOR_FUSIONCLOUD_HOST' || this.detailData.resourceType == 'MONITOR_H3C_HOST') {
if (
this.detailData.resourceType == 'MONITOR_VCENTER_HOST' ||
this.detailData.resourceType == 'MONITOR_CLOUDTOWER_HOST' ||
this.detailData.resourceType == 'MONITOR_OPENSTACK_HOST' ||
this.detailData.resourceType == 'MONITOR_FUSIONCLOUD_HOST' ||
this.detailData.resourceType == 'MONITOR_H3C_HOST'
) {
this.type = 'HOST'
}
const arr = []

View File

@ -0,0 +1,357 @@
<template>
<div>
<AdvanceTable title="当前告警" :search-configs="searchConfigs" :data="list" :params="params" :columns="columns" :get-list="getList" :total="total" :loading="loading" @select="handleSelectItem" @select-all="handleSelectAll" ref="currentMonitorTable">
<template v-slot:action>
<el-button type="ghost" @click="handleConfirm()" :disabled="!selectList.length">
批量确认
</el-button>
<el-button type="ghost" @click="handleBatchClear()" :disabled="!selectList.length">
批量清除
</el-button>
</template>
<template #name="val, record">
<span class="detail-href" @click="getDetail(record.id)">{{val}}</span>
</template>
<template #level="val">
<level-icon :color="alarmLevelColorFilter(val)">
{{alarmLevelFilter(val)}}
</level-icon>
</template>
<template #targetName="val, record">
<div v-if="record.type == 'MONITOR_ALIYUN_VM'">
<!-- <div v-for="(item, index) in parseTarget(val)" :key="index">{{item}}</div> -->
<span>{{parseTarget(val)}}</span>
</div>
<div v-else>{{val}}</div>
</template>
<template #resource="val, record">
{{resourceTypeMonitorFilter(record.type)}}<span v-if="record.type == 'VM'">({{record.osCategory}})</span>
</template>
<template #confirmed="val, record">
{{record.confirmed?'已确认':'未确认'}}{{record.solved?'已清除':'未清除'}}
</template>
<template #operate="val, record">
<el-button type="text" @click="handleConfirm(record.id)" :disabled="record.confirmed">
<i class="el-icon-check"></i> 确认
</el-button>
<div class="action-divider"></div>
<el-button type="text" @click="handleClear(record.id)" :disabled="record.solved">
<i class="el-icon-delete"></i> 清除
</el-button>
</template>
</AdvanceTable>
<el-dialog title="告警解决" :close-on-click-modal="false" v-if="solveFormVisible" :visible.sync="solveFormVisible">
<el-form :model="solveData" label-width="100px" ref="solveData">
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="解决结果:" prop="dealResult">
<el-input type="textarea" v-model="solveData.dealResult" auto-complete="off"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click.native="solveFormVisible = false">取消</el-button>
<el-button type="primary" @click.native="solveSubmit">确定</el-button>
</div>
</el-dialog>
<common-detail-right v-if="detailFlag" :title="detailData.name" @goBack="goBack">
<template v-slot:item_container>
<common-detail-item label="告警名称">{{detailData.name}}</common-detail-item>
<common-detail-item label="告警级别">
<level-icon :color="alarmLevelColorFilter(detailData.level)">
{{alarmLevelFilter(detailData.level)}}
</level-icon>
</common-detail-item>
<common-detail-item label="告警源">
<div v-if="detailData.type == 'MONITOR_ALIYUN_VM'">
{{parseTarget(detailData.targetName)}}
<!-- <div v-for="(item, index) in JSON.parse(detailData.targetName)" :key="index">{{item}}</div> -->
</div>
<div v-else>{{detailData.targetName}}</div>
</common-detail-item>
<common-detail-item label="资源类型">
{{resourceTypeMonitorFilter(detailData.type)}}<span v-if="detailData.type == 'VM'">({{detailData.osCategory}})
</span>
</common-detail-item>
<common-detail-item label="告警状态">{{detailData.status1}}</common-detail-item>
<common-detail-item label="告警内容">{{detailData.remark}}</common-detail-item>
<common-detail-item label="告警触发时间">{{detailData.gmtTrigger}}</common-detail-item>
<common-detail-item label="已持续时长">{{detailData.duration}}</common-detail-item>
<common-detail-item label="确认人">{{detailData.confirmer}}</common-detail-item>
<common-detail-item label="确认时间">{{detailData.gmtConfirm}}</common-detail-item>
</template>
</common-detail-right>
</div>
</template>
<script>
import { alarmLevelFilter, alarmLevelColorFilter, resourceTypeMonitorFilter } from '@/filters/index'
import { getAlarmList, alarmConfirm, alarmSolve, getAlarmDetail } from 'services/monitor'
import levelIcon from 'views/components/statusIcon'
const columns = [
{
type: 'selection',
disabled: true
},
{
label: '名称',
prop: 'name',
scopedSlots: { customRender: 'name' }
},
{
label: '告警级别',
prop: 'level',
scopedSlots: { customRender: 'level' }
},
{
label: '告警源',
prop: 'targetName',
scopedSlots: { customRender: 'targetName' }
},
{
label: '资源类型',
prop: 'resource',
scopedSlots: { customRender: 'resource' }
},
{
label: '告警状态',
prop: 'confirmed',
scopedSlots: { customRender: 'confirmed' }
},
{
label: '告警内容',
prop: 'remark'
},
{
label: '告警触发时间',
prop: 'gmtTrigger'
},
{
label: '已持续时长',
prop: 'duration'
},
{
label: '确认人',
prop: 'confirmer'
},
{
label: '确认时间',
prop: 'gmtConfirm'
},
{
label: '操作',
disabled: true,
prop: 'id',
width: '160px',
scopedSlots: { customRender: 'operate' }
}
]
const alarmLevelData = [
{ name: '提示告警', value: 'REMIND' },
{ name: '次要告警', value: 'SECONDARY' },
{ name: '重要告警', value: 'PRIMARY' },
{ name: '紧急告警', value: 'URGENT' }
]
export default {
components: {
levelIcon
},
props: {
target: {
type: Number
},
typeName: {
type: String
}
},
data () {
return {
alarmLevelFilter,
alarmLevelColorFilter,
resourceTypeMonitorFilter,
columns,
loading: false,
alarmLevelData,
searchConfigs: [
{ type: 'Input', label: '告警源', value: 'targetName' },
{ type: 'Select', label: '告警级别', value: 'level', data: alarmLevelData, props: { value: 'value' } },
{ type: 'DateRange', value: 'gmtTrigger', label: '' },
{ type: 'Const', value: 'type', initValue: this.typeName },
{ type: 'Const', value: 'target', initValue: this.target },
{ type: 'Const', value: 'eventAlarm', initValue: 0 },
{ type: 'Const', value: 'status', initValue: 'SOLVED', sign: 'UEQ' }
],
id: '',
params: {
page: 1,
rows: 10
},
total: 0,
list: [],
idList: [],
selectList: [],
solveFormVisible: false,
solveData: {},
detailFlag: false,
detailData: {}
}
},
created () {
this.id = this.$route.query.id;
},
beforeDestroy () {
},
methods: {
getList () {
this.loading = true
getAlarmList(this.params).then(data => {
this.loading = false
if (data.success) {
this.list = data.data.rows
this.total = data.data.total
this.list.forEach((item) => {
const self = this;
setTimeout(function () {
if (self.idList.indexOf(item.id) > -1) self.$refs.currentMonitorTable.toggleRowSelection(item, true)
})
})
}
})
},
//
handleSearch (params) {
this.params.page = 1
this.params.params = params
this.getList()
},
handleSelectItem (selection, row) {
this.refreshId()
if (this.idList.indexOf(row.id) > -1) {
for (let j = 0; j < this.selectList.length; j++) {
const item = this.selectList[j]
if (item.id == row.id) {
this.selectList.splice(j, 1)
break
}
}
} else {
this.selectList.push(row)
}
},
handleSelectAll (selection) {
this.refreshId()
if (selection.length) { //
this.list.forEach(item => {
if (this.idList.indexOf(item.id) == -1) {
this.selectList.push(item)
}
})
} else { //
this.list.forEach(item => {
if (this.idList.indexOf(item.id) > -1) {
for (let j = 0; j < this.selectList.length; j++) {
const row = this.selectList[j]
if (item.id == row.id) {
this.selectList.splice(j, 1)
break
}
}
}
})
}
},
refreshId () {
this.idList = []
this.selectList.forEach(item => {
this.idList.push(item.id)
})
},
handleConfirm (id) {
this.refreshId()
let list = []
if (id) {
list.push(id)
} else {
list = this.idList
}
this.$confirm('确定要确认告警吗?', '提示', {
confirmButtonText: '确认',
confirmButtonClass: 'el-button--primary',
type: 'warning'
}).then(() => {
alarmConfirm({
ids: list
}).then(data => {
if (data.success) {
this.$message.success({
message: data.message
})
this.getList()
}
})
}).catch(() => {
})
},
handleClear (id) {
this.solveData = {
ids: [id],
dealResult: ''
}
this.solveFormVisible = true;
},
handleBatchClear () {
this.refreshId();
this.solveData = {
ids: this.idList
}
this.solveFormVisible = true;
},
solveSubmit () {
this.$refs.solveData.validate((valid) => {
if (valid) {
alarmSolve(this.solveData).then(data => {
if (data.success) {
this.$message.success({
message: data.message
})
this.solveFormVisible = false
this.selectList = []
this.getList()
}
})
}
})
},
getDetail (id) {
getAlarmDetail(id).then(data => {
if (data.success) {
this.detailData = data.data
let str1, str2;
if (this.detailData.confirmed) {
str1 = '已确认'
} else {
str1 = '未确认'
}
if (this.detailData.solved) {
str2 = '已清除'
} else {
str2 = '未清除'
}
this.detailData.status1 = str1 + '' + str2
this.detailFlag = true
}
})
},
goBack () {
this.detailFlag = false
},
parseTarget(data) {
// TODO:
return data
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,301 @@
<template>
<div>
<AdvanceTable title="历史告警" :search-configs="searchConfigs" :data="list" :params="params" :columns="columns" :get-list="getList" :total="total" :loading="loading" @select="handleSelectItem" @select-all="handleSelectAll" ref="historyMonitorTable">
<template v-slot:action>
<el-button type="ghost" @click="handleConfirm()" :disabled="!selectList.length">
批量确认
</el-button>
</template>
<template #name="val, record">
<span class="detail-href" @click="getDetail(record.id)">{{val}}</span>
</template>
<template #level="val">
<level-icon :color="alarmLevelColorFilter(val)">
{{alarmLevelFilter(val)}}
</level-icon>
</template>
<template #targetName="val">
<!-- <div v-if="record.type == 'MONITOR_ALIYUN_VM'">
<div v-for="(item, index) in JSON.parse(val)" :key="index">{{item}}</div>
</div> -->
<div>{{val}}</div>
</template>
<template #resource="val, record">
{{resourceTypeMonitorFilter(record.type)}}<span v-if="record.type == 'VM'">({{record.osCategory}})</span>
</template>
<template #confirmed="val, record">
{{record.confirmed?'已确认':'未确认'}}{{record.solved?'已清除':'未清除'}}
</template>
<template #operate="val, record">
<el-button type="text" @click="handleConfirm(record.id)" :disabled="record.confirmed">
<i class="el-icon-check"></i> 确认
</el-button>
</template>
</AdvanceTable>
<common-detail-right v-if="detailFlag" :title="detailData.name" @goBack="goBack">
<template v-slot:item_container>
<common-detail-item label="告警名称">{{detailData.name}}</common-detail-item>
<common-detail-item label="告警级别">
<level-icon :color="alarmLevelColorFilter(detailData.level)">
{{alarmLevelFilter(detailData.level)}}
</level-icon>
</common-detail-item>
<common-detail-item label="告警源">
<!-- <div v-if="detailData.type == 'MONITOR_ALIYUN_VM'">
<div v-for="(item, index) in JSON.parse(detailData.targetName)" :key="index">{{item}}</div>
</div> -->
<div>{{detailData.targetName}}</div>
</common-detail-item>
<common-detail-item label="资源类型">
{{resourceTypeMonitorFilter(detailData.type)}}<span v-if="detailData.type == 'VM'">({{detailData.osCategory}})
</span>
</common-detail-item>
<common-detail-item label="告警状态">{{detailData.status1}}</common-detail-item>
<common-detail-item label="告警内容">{{detailData.remark}}</common-detail-item>
<common-detail-item label="告警触发时间">{{detailData.gmtTrigger}}</common-detail-item>
<common-detail-item label="已持续时长">{{detailData.duration}}</common-detail-item>
<common-detail-item label="确认人">{{detailData.confirmer}}</common-detail-item>
<common-detail-item label="确认时间">{{detailData.gmtConfirm}}</common-detail-item>
<common-detail-item label="解决人">{{detailData.solver}}</common-detail-item>
<common-detail-item label="解决时间">{{detailData.gmtSolve}}</common-detail-item>
<common-detail-item label="解决详情">{{detailData.dealResult}}</common-detail-item>
</template>
</common-detail-right>
</div>
</template>
<script>
import { alarmLevelFilter, alarmLevelColorFilter, resourceTypeMonitorFilter } from '@/filters/index'
import { getAlarmList, getAlarmDetail, alarmConfirm } from 'services/monitor'
import levelIcon from 'views/components/statusIcon'
const columns = [
{
type: 'selection',
disabled: true
},
{
label: '名称',
prop: 'name',
scopedSlots: { customRender: 'name' }
},
{
label: '告警级别',
prop: 'level',
scopedSlots: { customRender: 'level' }
},
{
label: '告警源',
prop: 'targetName',
scopedSlots: { customRender: 'targetName' }
},
{
label: '资源类型',
prop: 'resource',
scopedSlots: { customRender: 'resource' }
},
{
label: '告警状态',
prop: 'confirmed',
scopedSlots: { customRender: 'confirmed' }
},
{
label: '告警内容',
prop: 'remark'
},
{
label: '告警触发时间',
prop: 'gmtTrigger'
},
{
label: '已持续时长',
prop: 'duration'
},
{
label: '确认人',
prop: 'confirmer'
},
{
label: '确认时间',
prop: 'gmtConfirm'
},
{
label: '操作',
disabled: true,
prop: 'id',
width: '160px',
scopedSlots: { customRender: 'operate' }
}
]
const alarmLevelData = [
{ name: '提示告警', value: 'REMIND' },
{ name: '次要告警', value: 'SECONDARY' },
{ name: '重要告警', value: 'PRIMARY' },
{ name: '紧急告警', value: 'URGENT' }
]
export default {
components: {
levelIcon
},
props: {
target: {
type: Number
},
typeName: {
type: String
}
},
data () {
return {
alarmLevelFilter,
alarmLevelColorFilter,
resourceTypeMonitorFilter,
columns,
loading: false,
alarmLevelData,
searchConfigs: [
{ type: 'Input', label: '告警源', value: 'targetName' },
{ type: 'Select', label: '告警级别', value: 'level', data: alarmLevelData, props: { value: 'value' } },
{ type: 'DateRange', value: 'gmtTrigger', label: '' },
{ type: 'Const', value: 'type', initValue: this.typeName },
{ type: 'Const', value: 'target', initValue: this.target },
{ type: 'Const', value: 'eventAlarm', initValue: 0 },
{ type: 'Const', value: 'status', initValue: 'SOLVED' }
],
id: '',
params: {
page: 1,
rows: 10
},
total: 0,
list: [],
idList: [],
selectList: [],
detailFlag: false,
detailData: {}
}
},
created () {
this.id = this.$route.query.id;
},
beforeDestroy () {
},
methods: {
getList () {
this.loading = true
getAlarmList(this.params).then(data => {
this.loading = false
if (data.success) {
this.list = data.data.rows
this.total = data.data.total
this.list.forEach((item) => {
const self = this;
setTimeout(function () {
if (self.idList.indexOf(item.id) > -1) self.$refs.historyMonitorTable.toggleRowSelection(item, true)
})
})
}
})
},
//
handleSearch (params) {
this.params.page = 1
this.params.params = params
this.getList()
},
handleSelectItem (selection, row) {
this.refreshId()
if (this.idList.indexOf(row.id) > -1) {
for (let j = 0; j < this.selectList.length; j++) {
const item = this.selectList[j]
if (item.id == row.id) {
this.selectList.splice(j, 1)
break
}
}
} else {
this.selectList.push(row)
}
},
handleSelectAll (selection) {
this.refreshId()
if (selection.length) { //
this.list.forEach(item => {
if (this.idList.indexOf(item.id) == -1) {
this.selectList.push(item)
}
})
} else { //
this.list.forEach(item => {
if (this.idList.indexOf(item.id) > -1) {
for (let j = 0; j < this.selectList.length; j++) {
const row = this.selectList[j]
if (item.id == row.id) {
this.selectList.splice(j, 1)
break
}
}
}
})
}
},
refreshId () {
this.idList = []
this.selectList.forEach(item => {
this.idList.push(item.id)
})
},
handleConfirm (id) {
this.refreshId()
let list = []
if (id) {
list.push(id)
} else {
list = this.idList
}
this.$confirm('确定要确认告警吗?', '提示', {
confirmButtonText: '确认',
confirmButtonClass: 'el-button--primary',
type: 'warning'
}).then(() => {
alarmConfirm({
ids: list
}).then(data => {
if (data.success) {
this.$message.success({
message: data.message
})
this.getList()
}
})
}).catch(() => {
})
},
getDetail (id) {
getAlarmDetail(id).then(data => {
if (data.success) {
this.detailData = data.data
let str1, str2;
if (this.detailData.confirmed) {
str1 = '已确认'
} else {
str1 = '未确认'
}
if (this.detailData.solved) {
str2 = '已清除'
} else {
str2 = '未清除'
}
this.detailData.status1 = str1 + '' + str2
this.detailFlag = true
}
})
},
goBack () {
this.detailFlag = false
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,257 @@
<template>
<div>
<AdvanceTable title="" :search-configs="searchConfigs" :data="list" :params="params" :columns="columns" :get-list="getList" :total="total" :loading="loading" @select="handleSelectItem" @select-all="handleSelectAll" ref="resourceMonitorTable">
<template #name="val, record">
<span class="detail-href" @click="getDetail(record)">{{ val }}</span>
</template>
<template #cpuUsage="cpuUsage">
<el-progress class="progress" :color="customColorMethod" text-inside :stroke-width="16" :percentage="cpuUsage ? cpuUsage : 0"></el-progress>
</template>
<template #memUsage="memUsage">
<el-progress class="progress" :color="customColorMethod" text-inside :stroke-width="16" :percentage="memUsage ? memUsage : 0"></el-progress>
</template>
<template #onOffStatus="onOffStatus">
<status-icon :type="statusOnColorFilter(onOffStatus)">
{{ onOffStatus }}
</status-icon>
</template>
<template #responseTime="responseTime">
<span v-if="responseTime">{{ responseTime }}ms</span>
<span v-else></span>
</template>
<template #operate="val, record">
<el-button type="text" @click="handleMonitorDetail(record.id, record.name)"> 告警详情</el-button>
<div class="action-divider"></div>
<el-dropdown trigger="click">
<span class="el-dropdown-link"> 更多<i class="el-icon-arrow-down el-icon--right"></i> </span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="handleLink(record.id)"> 关联规则 </el-dropdown-item>
<el-dropdown-item @click.native="handlePolicy(record)">
{{ `${record.alarmEnable ? '屏蔽' : '开启'}告警` }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</AdvanceTable>
<add-policy v-if="addFlag" :resourceType="resourceType" @cancle="cancle" :add-link-flag="addFlag" :resourceId="resourceId" :ruleGroupIds="ruleGroupIds"></add-policy>
<common-detail v-if="detailFlag" :title="detailData.name" @goBack="goBack">
<div slot="custom_content">
<detail :detail-id="detailId" :detail-name="detailData.name"></detail>
</div>
</common-detail>
</div>
</template>
<script>
import { statusOnColorFilter } from '@/filters/index'
import { getPolicyHosts, getRuleGroupBind } from 'services/monitor/index.js'
import detail from './host_detail.vue'
import { customColorMethod, handleStart } from 'views/data'
import addPolicy from 'views/components/linkPolicy.vue'
const columns = [
{
type: 'selection',
disabled: true
},
{
label: '名称',
prop: 'name',
scopedSlots: { customRender: 'name' }
},
{
label: 'IP地址',
prop: 'manageIp'
},
{
label: 'CPU利用率',
prop: 'cpuUsage',
scopedSlots: { customRender: 'cpuUsage' }
},
{
label: '内存利用率',
prop: 'memUsage',
scopedSlots: { customRender: 'memUsage' }
},
{
label: '总CPU(MHZ)',
prop: 'cpuTotal'
},
{
label: '总内存(GB)',
prop: 'memTotal'
},
{
label: '云主机数',
prop: 'vmNum'
},
// {
// label: '',
// prop: 'onOffStatus',
// scopedSlots: { customRender: 'onOffStatus' }
// },
// {
// label: '',
// prop: 'responseTime',
// scopedSlots: { customRender: 'responseTime' }
// },
{
label: '操作',
disabled: true,
prop: 'id',
width: '160px',
scopedSlots: { customRender: 'operate' }
}
]
export default {
components: {
detail,
addPolicy
},
data() {
return {
statusOnColorFilter,
customColorMethod,
handleStart,
columns,
searchConfigs: [
{ type: 'Input', label: '名称', value: 'name' },
{ type: 'Input', label: 'IP', value: 'manageIp' },
{ type: 'Const', value: 'vendorType', initValue: 'CLOUDTOWER' },
{ type: 'Const', value: 'vendorId', initValue: this.$route.query.vendorId }
],
params: {
page: 1,
rows: 10
},
vendorData: [],
list: [],
total: 0,
idList: [],
selectList: [],
detailFlag: false,
detailData: {},
detailId: null,
loading: false,
addFlag: false,
resourceId: 0,
ruleGroupIds: [],
resourceType: 'MONITOR_CLOUDTOWER_HOST'
}
},
methods: {
getList() {
this.loading = true
this.refreshId()
getPolicyHosts(this.params).then((data) => {
this.loading = false
if (data.success) {
this.list = data.data.rows
this.total = data.data.total
this.list.forEach((item) => {
item.cpuUsage = Number(item.cpuUsage).toFixed(2) * 1
item.memUsage = Number(item.memUsage).toFixed(2) * 1
switch (item.onOffStatus) {
case '0':
item.onOffStatus = '断开'
break
case '1':
item.onOffStatus = '正常'
break
default:
item.onOffStatus = '未知'
break
}
const self = this
setTimeout(function () {
if (self.idList.indexOf(item.id) > -1) self.$refs.resourceMonitorTable.toggleRowSelection(item, true)
})
})
}
})
},
handleSelectItem(selection, row) {
this.refreshId()
if (this.idList.indexOf(row.id) > -1) {
for (let j = 0; j < this.selectList.length; j++) {
const item = this.selectList[j]
if (item.id == row.id) {
this.selectList.splice(j, 1)
break
}
}
} else {
this.selectList.push(row)
}
},
handleSelectAll(selection) {
this.refreshId()
if (selection.length) {
//
selection.forEach((item) => {
if (this.idList.indexOf(item.id) == -1) {
this.selectList.push(item)
}
})
} else {
//
this.list.forEach((item) => {
if (this.idList.indexOf(item.id) > -1) {
for (let j = 0; j < this.selectList.length; j++) {
const row = this.selectList[j]
if (item.id == row.id) {
this.selectList.splice(j, 1)
break
}
}
}
})
}
},
refreshId() {
this.idList = []
this.selectList.forEach((item) => {
this.idList.push(item.id)
})
},
handleSearch(params) {
this.params.page = 1
this.params.params = params
this.getList()
},
handleLink(id, flag) {
this.ruleGroupIds = []
this.resourceId = id
getRuleGroupBind(id).then((data) => {
if (data.success) {
this.ruleGroupIds = data.data
this.addFlag = true
}
})
},
cancle() {
this.addFlag = false
this.getList()
},
handlePolicy(data) {
this.handleStart(this, data, this.resourceType)
},
getDetail(row) {
this.detailId = row.id
this.detailData = {
name: row.name
}
this.detailFlag = true
},
goBack() {
this.detailFlag = false
},
handleMonitorDetail(id, name) {
this.$router.push({
name: 'MonitorDetailList',
query: { id: id, name: name, type: this.resourceType }
})
}
},
created() {}
}
</script>

View File

@ -0,0 +1,66 @@
<template>
<div>
<detail-map :detail="detailData" :list="detailMapList"></detail-map>
<el-row :gutter="5">
<el-col :span="12" v-for="chart in typeData" :key="chart.value">
<chart-box :params-data="chart" :item-data="dashboradData[chart.value]"></chart-box>
</el-col>
</el-row>
</div>
</template>
<script>
import detailMap from 'views/components/detailMap.vue'
import { getCharts, getHostCpu } from 'services/monitor'
import chartBox from 'views/components/chartBox.vue'
export default {
components: { detailMap, chartBox },
props: {
detailId: {
type: Number
},
detailName: {
type: String
},
address: {
type: String
}
},
data() {
return {
detailData: {},
typeData: [{ title: 'CPU利用率', value: 'usage', expr: JSON.stringify(['round(bocloud_cloudtower_host_host_cpu_overall_usage_percent{id="' + this.detailId + '"}, 0.01)']), name: '["cpu利用率"]', unit: '%' }],
detailMapList: [
{ name: 'CPU类型', value: 'cpuModel', unit: '' },
{ name: 'CPU数量', value: 'cpuAmount', unit: '' },
{ name: 'CPU核数', value: 'cpuCore', unit: '' },
{ name: 'CPU总量', value: 'cpuTotal', unit: 'MHZ' },
{ name: 'CPU使用量', value: 'cpuUsed', unit: 'MHZ' },
{ name: 'CPU空闲量', value: 'cpuFree', unit: 'MHZ' }
],
dashboradData: {
usage: {}
},
userDefindVisible: false,
userDefindTime: []
}
},
methods: {
getCpu() {
getHostCpu(this.detailId).then((data) => {
if (data.success) {
this.detailData = Object.assign({}, data.data)
}
})
}
},
created() {
for (const key in this.dashboradData) {
const element = this.dashboradData[key]
this.$set(element, 'step', null)
this.$set(element, 'stepValue', 20)
this.$set(element, 'defindTime', [])
}
this.getCpu()
}
}
</script>

View File

@ -0,0 +1,60 @@
<template>
<div>
<detail-map :detail="detailData" :list="detailMapList"></detail-map>
<el-row :gutter="20">
<el-col :span="12" v-for="chart in typeData" :key="chart.value">
<chart-box :params-data="chart" :item-data="dashboradData[chart.value]"></chart-box>
</el-col>
</el-row>
</div>
</template>
<script>
import detailMap from 'views/components/detailMap.vue'
import { getCharts, getHostMem } from 'services/monitor'
import chartBox from 'views/components/chartBox.vue'
export default {
components: { detailMap, chartBox },
props: {
detailId: {
type: Number
},
detailName: {
type: String
}
},
data() {
return {
typeData: [{ title: '内存利用率', value: 'usage', expr: JSON.stringify(['round(bocloud_cloudtower_host_host_memory_usage_percent{id="' + this.detailId + '"}, 0.01)']), name: "['内存利用率']", unit: '%' }],
detailData: {},
detailMapList: [
{ name: '内存总量', value: 'memTotalCapacity', unit: 'GB' },
{ name: '内存使用量', value: 'memUsed', unit: 'GB' },
{ name: '内存空闲量', value: 'memFree', unit: 'GB' }
],
dashboradData: {
usage: {}
},
userDefindVisible: false,
userDefindTime: []
}
},
methods: {
getDetail() {
getHostMem(this.detailId).then((data) => {
if (data.success) {
this.detailData = Object.assign({}, data.data)
}
})
}
},
created() {
this.getDetail()
for (const key in this.dashboradData) {
const element = this.dashboradData[key]
this.$set(element, 'step', null)
this.$set(element, 'stepValue', 20)
this.$set(element, 'defindTime', [])
}
}
}
</script>

View File

@ -0,0 +1,41 @@
<template>
<el-row :gutter="20">
<el-col :span="12" v-for="chart in typeData" :key="chart.value">
<chart-box :params-data="chart" :item-data="dashboradData[chart.value]"></chart-box>
</el-col>
</el-row>
</template>
<script>
import chartBox from 'views/components/chartBox.vue'
export default {
components: { chartBox },
props: {
detailId: {
type: Number
},
detailName: {
type: String
}
},
data() {
return {
typeData: [
{ title: '网络发送速率', value: 'read', expr: JSON.stringify(['round(bocloud_cloudtower_host_host_network_transmit_speed_bitps{id="' + this.detailId + '"}, 0.01)']), name: "['网络发送速率']", unit: 'bitps' },
{ title: '网络接收速率', value: 'write', expr: JSON.stringify(['round(bocloud_cloudtower_host_host_network_receive_speed_bitps{id="' + this.detailId + '"}, 0.01)']), name: "['网络接收速率']", unit: 'bitps' }
],
dashboradData: {
read: {},
write: {}
}
}
},
created() {
for (const key in this.dashboradData) {
const element = this.dashboradData[key]
this.$set(element, 'step', null)
this.$set(element, 'stepValue', 20)
this.$set(element, 'defindTime', [])
}
}
}
</script>

View File

@ -0,0 +1,140 @@
<template>
<div>
<detail-map :detail="detailData" :list="detailMapList"></detail-map>
<el-row :gutter="5">
<el-col :span="12">
<el-card class="box-card m-t-xs" style="height: 289px">
<div slot="header" class="clearfix">
<span>使用情况</span>
</div>
<div class="text-center">
<el-col :span="12">
<div>CPU利用率</div>
<gauge-charts v-if="dashboardData.cpuUsage1" height="190px" id="cpuUsage" width="100%" :data="dashboardData.cpuUsage1"></gauge-charts>
</el-col>
<el-col :span="12">
<div>内存利用率</div>
<gauge-charts v-if="dashboardData.memUsage1" height="190px" id="memUsage" width="100%" :data="dashboardData.memUsage1"></gauge-charts>
</el-col>
</div>
</el-card>
</el-col>
<el-col :span="12" v-for="chart in typeData" :key="chart.value">
<chart-box :params-data="chart" :item-data="paramsOverviewChart[chart.value]"></chart-box>
</el-col>
</el-row>
</div>
</template>
<script>
import detailMap from 'views/components/detailMap.vue'
import { getCharts, getHostDashboard, getHostDetail } from 'services/monitor'
import chartBox from 'views/components/chartBox.vue'
export default {
components: {
detailMap,
chartBox
},
props: {
detailId: {
type: Number
},
detailName: {
type: String
}
},
data() {
return {
typeData: [
{
title: 'CPU利用率',
value: 'cpu',
expr: JSON.stringify(['round(bocloud_cloudtower_host_host_cpu_overall_usage_percent{id="' + this.detailId + '"}, 0.01)']),
name: '["cpu利用率"]',
unit: '%'
},
{
title: '内存利用率',
value: 'mem',
expr: JSON.stringify(['round(bocloud_cloudtower_host_host_memory_usage_percent{id="' + this.detailId + '"}, 0.01)']),
name: "['内存利用率']",
unit: '%'
},
{ title: '磁盘读取速率', value: 'read', expr: JSON.stringify(['round(bocloud_cloudtower_host_zbs_chunk_read_iops{id="' + this.detailId + '"}, 0.01)']), name: "['磁盘读取速率']", unit: '%' }
],
detailData: {},
detailMapList: [
{ name: 'IP', value: 'ip', unit: '' },
{ name: '总CPU', value: 'cpuCapacity', unit: 'MHz', img: '/web-common-resource/img/detail/cpu.png' },
{ name: '总内存', value: 'memoryCapacity', unit: 'GB', img: '/web-common-resource/img/detail/memorys.png' },
{ name: '云主机', value: 'vmNum', unit: '台', img: '/web-common-resource/img/detail/vms.png' }
],
dashboardData: {},
paramsOverviewChart: {
cpu: {},
mem: {},
read: {},
write: {}
},
userDefindTime: [],
userDefindVisible: false,
timeIntervalDashboard: ''
}
},
methods: {
getDetail() {
getHostDetail(this.detailId, 'CLOUDTOWER').then((data) => {
if (data.success) {
this.detailData = Object.assign({}, data.data)
}
})
},
getDashboard() {
const expr1 = 'round(bocloud_cloudtower_host_host_cpu_overall_usage_percent{id="' + this.detailId + '"}, 0.01)'
const expr2 = 'round(bocloud_cloudtower_host_host_memory_usage_percent{id="' + this.detailId + '"}, 0.01)'
getHostDashboard({
expr: expr1,
simple: true
}).then((data) => {
if (data.success) {
this.$set(this.dashboardData, 'cpuUsage1', {
name: 'CPU利用率',
data: { value: data.data, name: '%' },
min: 0,
max: 100
})
}
})
getHostDashboard({
expr: expr2,
simple: true
}).then((data) => {
if (data.success) {
this.$set(this.dashboardData, 'memUsage1', {
name: '内存利用率',
data: { value: data.data, name: '%' },
min: 0,
max: 100
})
}
})
if (this.timeIntervalDashboard) {
clearInterval(this.timeIntervalDashboard)
this.timeIntervalDashboard = ''
}
this.timeIntervalDashboard = setInterval(() => {
this.getDashboard()
}, 60 * 1000)
}
},
created() {
this.getDetail()
this.getDashboard()
for (const key in this.paramsOverviewChart) {
const element = this.paramsOverviewChart[key]
this.$set(element, 'step', null)
this.$set(element, 'stepValue', 20)
this.$set(element, 'defindTime', [])
}
}
}
</script>

View File

@ -0,0 +1,62 @@
<template>
<div>
<detail-map :detail="detailData" :list="detailMapList"></detail-map>
<el-row :gutter="20">
<el-col :span="12" v-for="chart in typeData" :key="chart.value">
<chart-box :params-data="chart" :item-data="dashboradData[chart.value]"></chart-box>
</el-col>
</el-row>
</div>
</template>
<script>
import detailMap from 'views/components/detailMap.vue'
import { getCharts, getHostDisk } from 'services/monitor'
import chartBox from 'views/components/chartBox.vue'
export default {
components: { detailMap, chartBox },
props: {
detailId: {
type: Number
},
detailName: {
type: String
}
},
data() {
return {
typeData: [
{ title: '磁盘读取速率', value: 'read', expr: JSON.stringify(['round(bocloud_cloudtower_host_zbs_chunk_read_iops{id="' + this.detailId + '"}, 0.01)']), name: "['磁盘读取速率']", unit: '%' },
{ title: '磁盘写入速率', value: 'write', expr: JSON.stringify(['round(bocloud_cloudtower_host_zbs_chunk_write_iops{id="' + this.detailId + '"}, 0.01)']), name: "['磁盘读取速率']", unit: '%' }
],
detailData: {},
detailMapList: [
{ name: '磁盘总量', value: 'diskCapacity', unit: 'GB' },
{ name: '磁盘使用量', value: 'diskUsed', unit: 'GB' },
{ name: '磁盘空闲量', value: 'diskFree', unit: 'GB' }
],
dashboradData: {
read: {},
write: {}
}
}
},
methods: {
getDetail() {
getHostDisk(this.detailId).then((data) => {
if (data.success) {
this.detailData = Object.assign({}, data.data)
}
})
}
},
created() {
this.getDetail()
for (const key in this.dashboradData) {
const element = this.dashboradData[key]
this.$set(element, 'step', null)
this.$set(element, 'stepValue', 20)
this.$set(element, 'defindTime', [])
}
}
}
</script>

View File

@ -0,0 +1,80 @@
<template>
<el-dialog title="自定义时间" :close-on-click-modal="false" v-if="userDefindVisible" :visible.sync="userDefindVisible" append-to-body>
<basic-form>
<basic-form-item label="选择时间:">
<el-date-picker
v-model="time"
type="datetimerange"
size="mini"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="timestamp"
:picker-options="pickerOptions"></el-date-picker>
</basic-form-item>
</basic-form>
<div slot="footer" class="dialog-footer">
<el-button type="ghost" @click.native="close">取消</el-button>
<el-button type="primary" @click.native="userDefindSubmit">确定</el-button>
</div>
</el-dialog>
</template>
<script>
export default {
props: {
userDefindVisible: {
type: Boolean
},
userDefindTime: {
type: Array
}
},
data () {
return {
time: [],
pickerMinDate: '',
dateRange: [],
pickerOptions: {
onPick: ({ maxDate, minDate }) => {
this.pickerMinDate = minDate.getTime()
if (maxDate) {
this.pickerMinDate = ''
}
},
disabledDate: (time) => {
if (this.pickerMinDate !== '') {
const day14 = (14 - 1) * 24 * 3600 * 1000
let maxTime = this.pickerMinDate + day14
const minTime = this.pickerMinDate - day14
if (maxTime > new Date()) {
maxTime = new Date()
}
return time.getTime() > maxTime || time.getTime() < minTime
}
return time.getTime() > Date.now()
}
}
}
},
created () {
this.time = [];
if (this.userDefindTime.length) {
this.time.push(this.userDefindTime[0], this.userDefindTime[1])
}
},
methods: {
userDefindSubmit () {
if (this.time && this.time.length && this.time[0] != undefined) {
this.$emit('getData', this.time);
} else {
return this.$message.error('请选择自定义时间!');
}
},
close () {
this.$emit('getData');
}
}
}
</script>

View File

@ -0,0 +1,55 @@
<template>
<el-card>
<el-tabs v-model="activeName" class="m-t-n-md">
<el-tab-pane name="overview" label="资源总览">
<overview ref="overview" v-if="activeName == 'overview'" :detail-id="detailId" :detail-name="detailName"></overview>
</el-tab-pane>
<el-tab-pane name="cpu" label="CPU">
<cpu ref="cpu" v-if="activeName == 'cpu'" :detail-id="detailId" :detail-name="detailName"></cpu>
</el-tab-pane>
<el-tab-pane name="mem" label="内存">
<mem ref="mem" v-if="activeName == 'mem'" :detail-id="detailId" :detail-name="detailName"></mem>
</el-tab-pane>
<el-tab-pane name="storage" label="磁盘">
<storage ref="storage" v-if="activeName == 'storage'" :detail-id="detailId" :detail-name="detailName"></storage>
</el-tab-pane>
<el-tab-pane name="net" label="网络">
<net ref="net" v-if="activeName == 'net'" :detail-id="detailId" :detail-name="detailName"></net>
</el-tab-pane>
</el-tabs>
</el-card>
</template>
<script>
import overview from './hostDetail/overview.vue'
import cpu from './hostDetail/cpu.vue'
import mem from './hostDetail/mem.vue'
import storage from './hostDetail/storage.vue'
import net from './hostDetail/net.vue'
export default {
components: {
overview,
cpu,
mem,
storage,
net
},
props: {
detailId: {
type: Number
},
detailName: {
type: String
}
},
data() {
return {
activeName: 'overview'
}
},
methods: {},
created() {},
mounted() {}
}
</script>
<style scoped></style>

View File

@ -0,0 +1,69 @@
<template>
<el-card class="wrapper">
<div slot="header" class="clearfix">
<div class="detail-header">
<span class="detail-back" @click="goBack"><i class="iconfont icon-left-arrow"></i> 返回</span>
<span class="line"></span>
<span class="title">{{ $route.query.vendorName }}</span>
</div>
</div>
<el-tabs ref="resourceMonitorTab" type="card" @tab-click="handleClick" v-model="activeName">
<el-tab-pane name="dashboard" label="概览">
<dashboard ref="Dashboard" v-if="activeName == 'dashboard'"></dashboard>
</el-tab-pane>
<el-tab-pane name="host" label="宿主机">
<host v-if="activeName == 'host'" ref="monitorHost"></host>
</el-tab-pane>
<el-tab-pane name="vm" label="云主机">
<vm v-if="activeName == 'vm'" ref="monitorVm"></vm>
</el-tab-pane>
</el-tabs>
</el-card>
</template>
<script>
import host from './host.vue'
import vm from './vm.vue'
import dashboard from 'views/components/dashboard.vue'
export default {
components: {
dashboard,
host,
vm
},
data() {
return {
activeName: 'dashboard'
}
},
methods: {
handleClick() {},
goBack() {
history.go(-1)
}
},
created() {},
mounted() {}
}
</script>
<style scoped>
.detail-header .detail-back {
color: #46abf1;
cursor: pointer;
}
.detail-header .line {
position: relative;
top: 4px;
margin: 0 6px;
height: 14px;
width: 1px;
display: inline-block;
background-color: #b5b5b5;
}
.detail_icon {
font-size: 25px;
margin: 10px;
color: #409eff;
}
</style>

View File

@ -0,0 +1,187 @@
<template>
<div class="wrapper">
<div>
<div slot="header" class="clearfix">
<div class="detail-header">
<span class="detail-back" @click="goBack"><i class="iconfont icon-left-arrow"></i> 返回</span>
<span class="line"></span>
<span class="title">{{ $route.query.name }}</span>
</div>
</div>
<el-tabs ref="monitorList" v-model="activeName" type="border-card">
<el-tab-pane label="当前告警" name="current">
<current-monitor v-if="activeName == 'current'" :target="target" :typeName="type" ref="currentMonitor"></current-monitor>
</el-tab-pane>
<el-tab-pane label="历史告警" name="history">
<history-monitor v-if="activeName == 'history'" :target="target" :typeName="type" ref="historyMonitor"></history-monitor>
</el-tab-pane>
</el-tabs>
<el-row class="m-t-xs" :gutter="5">
<el-col :span="10">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>告警统计</span>
</div>
<pie-charts ref="chart1" v-if="chart1Data" id="chart1" :data="chart1Data" width="100%" :setting="{ color: ['#EC1C24', '#FF7F27', '#FFF200', '#4EAFF5'] }" height="250px" theme="告警统计"></pie-charts>
</el-card>
</el-col>
<el-col :span="14">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>告警统计</span>
<span class="pull-right">
<el-button-group>
<el-button size="mini" :type="item.value == chart2.step ? 'primary' : ''" v-for="item in intervalData" :key="item.value" @click="changeInterval(item.value)">{{ item.name }}</el-button>
<el-button size="mini" :type="chart2.step === 0 ? 'primary' : ''" @click="userDefind()"></el-button>
</el-button-group>
</span>
</div>
<div>
<bar-charts ref="chart2" height="250px" width="100%" id="cpu" :data="chart2Data" :setting="{ color: ['#EC1C24', '#FF7F27', '#FFF200', '#4EAFF5'] }" v-if="chart2Data"></bar-charts>
</div>
</el-card>
</el-col>
</el-row>
<el-dialog title="自定义时间" :close-on-click-modal="false" v-if="userDefindVisible" :visible.sync="userDefindVisible">
<basic-form>
<basic-form-item label="选择时间:">
<el-date-picker v-model="userDefindTime2" type="datetimerange" size="mini" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" value-format="timestamp" :picker-options="pickerOptions"></el-date-picker>
</basic-form-item>
</basic-form>
<div slot="footer" class="dialog-footer">
<el-button type="ghost" @click.native="close">取消</el-button>
<el-button type="primary" @click.native="userDefindSubmit">确定</el-button>
</div>
</el-dialog>
</div>
</div>
</template>
<script>
import currentMonitor from './currentMonitor.vue'
import historyMonitor from './historyMonitor.vue'
import { getAlarmChart } from 'services/monitor'
const intervalData = [
{ name: '7D', value: '7' },
{ name: '15D', value: '15' },
{ name: '1M', value: '30' }
]
export default {
components: {
currentMonitor,
historyMonitor
},
data() {
return {
intervalData,
target: this.$route.query.id,
type: this.$route.query.type,
activeName: 'current',
chart1Data: null,
chart2Data: null,
chart2: {
step: null
},
userDefindTime: [],
userDefindTime2: [],
userDefindVisible: false,
pickerOptions: {
disabledDate: (time) => {
return time.getTime() > Date.now()
}
}
}
},
created() {
this.getPieData()
this.changeInterval(7)
},
beforeDestroy() {},
methods: {
getPieData() {
getAlarmChart({
action: 'pieChart',
target: this.target,
type: this.type
}).then((data) => {
if (data.success) {
this.chart1Data = data.data
}
})
},
getBarData() {
getAlarmChart({
action: 'barChart',
target: this.target,
type: this.type,
start: this.chart2.start,
end: this.chart2.end
}).then((data) => {
if (data.success) {
this.chart2Data = data.data
}
})
},
//
changeInterval(value) {
this.userDefindTime = []
this.userDefindTime2 = []
this.chart2.step = value
// 0
const timeStamp = new Date(new Date().setHours(0, 0, 0, 0)) / 1000
this.chart2.end = timeStamp
// 86400 value
this.chart2.start = timeStamp - 86400 * value
this.getBarData()
},
userDefind() {
this.userDefindTime2 = Object.assign([], this.userDefindTime)
this.userDefindVisible = true
},
userDefindSubmit() {
this.userDefindTime = Object.assign([], this.userDefindTime2)
if (this.userDefindTime.length) {
this.chart2.step = 0
this.chart2.end = Math.round(this.userDefindTime[1] / 1000)
this.chart2.start = Math.round(this.userDefindTime[0] / 1000)
this.getBarData()
this.userDefindVisible = false
} else {
return this.$message.error('请选择自定义时间!')
}
},
close() {
this.userDefindVisible = false
},
goBack() {
history.go(-1)
}
}
}
</script>
<style scoped>
.detail-header {
padding-bottom: 10px;
margin-bottom: 10px;
border-bottom: 1px solid #e6e6e6;
}
.detail-header .detail-back {
color: #46abf1;
cursor: pointer;
}
.detail-header .line {
position: relative;
top: 4px;
margin: 0 6px;
height: 14px;
width: 1px;
display: inline-block;
background-color: #b5b5b5;
}
.detail_icon {
font-size: 25px;
margin: 10px;
color: #409eff;
}
</style>

View File

@ -0,0 +1,274 @@
<template>
<div>
<AdvanceTable title="" :search-configs="searchConfigs" :data="list" :params="params" :columns="vmColumns" :get-list="getList" :total="total" :loading="loading" @select="handleSelectItem" @select-all="handleSelectAll" ref="resourceMonitorTable">
<template #name="val, record">
<span class="detail-href" @click="getDetail(record)">{{ val }}</span>
</template>
<template #privateIps="privateIps, record">
{{ record.managerIp }}
</template>
<template #status="status">
<status-icon :type="vmStatusColorFilter(status)">{{ vmStatusFilter(status) }} </status-icon>
</template>
<template #cpuUsage="cpuUsage">
<el-progress class="progress" :color="customColorMethod" text-inside :stroke-width="16" :percentage="cpuUsage ? cpuUsage : 0"></el-progress>
</template>
<template #memUsage="memUsage">
<el-progress class="progress" :color="customColorMethod" text-inside :stroke-width="16" :percentage="memUsage ? memUsage : 0"></el-progress>
</template>
<template #onOffStatus="onOffStatus">
<status-icon :type="statusOnColorFilter(onOffStatus)">
{{ onOffStatus }}
</status-icon>
</template>
<template #responseTime="responseTime">
<span v-if="responseTime">{{ responseTime }}ms</span>
<span v-else></span>
</template>
<template #operate="val, record">
<el-button type="text" @click="handleMonitorDetail(record.id, record.name)"> 告警详情</el-button>
<div class="action-divider"></div>
<el-dropdown trigger="click">
<span class="el-dropdown-link"> 更多<i class="el-icon-arrow-down el-icon--right"></i> </span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="handleLink(record.id)"> 关联规则 </el-dropdown-item>
<el-dropdown-item @click.native="handlePolicy(record)">
{{ `${record.alarmEnable ? '屏蔽' : '开启'}告警` }}
</el-dropdown-item>
<el-dropdown-item @click.native="setIP(record)"> 设置监控IP </el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</AdvanceTable>
<add-policy v-if="addFlag" resourceType="MONITOR_CLOUDTOWER_VM" @cancle="cancle" :add-link-flag="addFlag" :resourceId="resourceId" :ruleGroupIds="ruleGroupIds"></add-policy>
<el-dialog title="设置监控IP" :visible.sync="setIPFlag" v-if="setIPFlag">
<el-row>
<basic-form ref="setData" :model="setData" :status-icon="true">
<el-col :span="24">
<basic-form-item label="IP地址" prop="ip" validate="required">
<el-select filterable clearable v-model="setData.ip">
<el-option v-for="(item, index) in ipData" :key="index" :label="item.address" :value="item.address"></el-option>
</el-select>
</basic-form-item>
</el-col>
</basic-form>
</el-row>
<span slot="footer" class="dialog-footer">
<el-button type="ghost" @click.native="setIPFlag = false"> </el-button>
<el-button type="primary" @click.native="setSubmit"> </el-button>
</span>
</el-dialog>
<common-detail v-if="detailFlag" :title="detailData.name" @goBack="goBack">
<div slot="custom_content">
<detail :detail-id="detailId" :identifier="identifier" :host-name="hostName" :bios-uuid="biosUuid"></detail>
</div>
</common-detail>
</div>
</template>
<script>
import { statusOnColorFilter, vmStatusFilter, vmStatusColorFilter } from '@/filters/index'
import { getVms, setIps, getRuleGroupBind } from 'services/monitor/index.js'
import { vmColumns, customColorMethod, handleStart } from 'views/data'
import detail from './vm_detail.vue'
import addPolicy from 'views/components/linkPolicy.vue'
export default {
components: {
detail,
addPolicy
},
data() {
return {
statusOnColorFilter,
vmStatusFilter,
vmStatusColorFilter,
vmColumns,
handleStart,
searchConfigs: [
{ type: 'Input', label: '名称', value: 'name' },
{ type: 'Input', label: 'IP', value: 'privateIps' },
{
type: 'Select',
label: '状态',
value: 'status',
data: [
{ id: 'RUNNING', name: '运行中' },
{ id: 'BUILDING', name: '创建中' },
{ id: 'STOPPED', name: '关机' },
{ id: 'SUSPENDED', name: '挂起' },
{ id: 'EXCEPTION', name: '异常' },
{ id: 'UNKNOWN', name: '断开' }
]
},
{ type: 'Const', value: 'vendorType', initValue: 'CLOUDTOWER' },
{ type: 'Const', value: 'vendorId', initValue: this.$route.query.vendorId },
{ type: 'Const', value: 'isTemplate', initValue: false }
],
customColorMethod,
params: {
page: 1,
rows: 10
},
list: [],
total: 0,
idList: [],
selectList: [],
detailFlag: false,
detailId: null,
identifier: '',
setData: {},
ipData: [],
setIPFlag: false,
loading: false,
hostName: '',
addFlag: false,
resourceId: 0,
ruleGroupIds: [],
biosUuid: ''
}
},
methods: {
getList() {
this.refreshId()
this.loading = true
getVms(this.params).then((data) => {
this.loading = false
if (data.success) {
this.list = data.data.rows
this.total = data.data.total
this.list.forEach((item) => {
item.cpuUsage = Number(item.cpuUsage)
item.memUsage = Number(item.memUsage)
if (item.privateIps) {
item.privateIps = JSON.parse(item.privateIps)
}
switch (item.onOffStatus) {
case '0':
item.onOffStatus = '断开'
break
case '1':
item.onOffStatus = '正常'
break
default:
item.onOffStatus = '未知'
break
}
const self = this
setTimeout(function () {
if (self.idList.indexOf(item.id) > -1) self.$refs.resourceMonitorTable.toggleRowSelection(item, true)
})
})
}
})
},
handleSelectItem(selection, row) {
this.refreshId()
if (this.idList.indexOf(row.id) > -1) {
for (let j = 0; j < this.selectList.length; j++) {
const item = this.selectList[j]
if (item.id == row.id) {
this.selectList.splice(j, 1)
break
}
}
} else {
this.selectList.push(row)
}
},
handleSelectAll(selection) {
this.refreshId()
if (selection.length) {
//
selection.forEach((item) => {
if (this.idList.indexOf(item.id) == -1) {
this.selectList.push(item)
}
})
} else {
//
this.list.forEach((item) => {
if (this.idList.indexOf(item.id) > -1) {
for (let j = 0; j < this.selectList.length; j++) {
const row = this.selectList[j]
if (item.id == row.id) {
this.selectList.splice(j, 1)
break
}
}
}
})
}
},
refreshId() {
this.idList = []
this.selectList.forEach((item) => {
this.idList.push(item.id)
})
},
handleSearch(params) {
this.params.page = 1
this.params.params = params
this.getList()
},
handleLink(id, flag) {
this.ruleGroupIds = []
this.resourceId = id
getRuleGroupBind(id).then((data) => {
if (data.success) {
this.ruleGroupIds = data.data
this.addFlag = true
}
})
},
cancle() {
this.addFlag = false
this.getList()
},
handlePolicy(data) {
this.handleStart(this, data, 'MONITOR_CLOUDTOWER_VM')
},
getDetail(row) {
this.detailId = row.id
this.identifier = row.name
this.hostName = row.hostName
this.biosUuid = row.biosUuid
this.detailData = {
name: row.name
}
this.detailFlag = true
},
goBack() {
this.detailFlag = false
},
handleMonitorDetail(id, name) {
this.$router.push({
name: 'MonitorDetailList',
query: { id: id, name: name, type: 'MONITOR_CLOUDTOWER_VM' }
})
},
setIP(row) {
this.setData = {
id: row.id,
ip: row.monitorIp
}
this.ipData = row.privateIps
this.setIPFlag = true
},
setSubmit() {
this.$refs.setData.validate((valid) => {
if (valid) {
setIps(this.setData).then((data) => {
this.$notify({
message: data.message,
type: 'success'
})
this.setIPFlag = false
this.getList()
})
}
})
}
},
created() {}
}
</script>

View File

@ -0,0 +1,53 @@
<template>
<div>
<el-row :gutter="5">
<el-col :span="12" v-for="chart in typeData" :key="chart.value">
<chart-box :params-data="chart" :item-data="dashboradData[chart.value]"></chart-box>
</el-col>
</el-row>
</div>
</template>
<script>
import chartBox from 'views/components/chartBox.vue'
import { init } from 'views/components/util'
export default {
components: { chartBox },
props: {
detailId: {
type: Number
},
identifier: {
type: String
},
hostName: {
type: String
}
},
data() {
return {
typeData: [
{
title: 'CPU利用率',
value: 'usage',
expr: JSON.stringify(['round(bocloud_cloudtower_vm_elf_vm_cpu_overall_usage_percent{id="' + this.detailId + '"}, 0.01)']),
name: "['CPU利用率']",
unit: '%'
}
],
dashboradData: {
usage: {}
}
}
},
beforeDestroy() {},
methods: {},
created() {
for (const key in this.dashboradData) {
const element = this.dashboradData[key]
this.$set(element, 'step', null)
this.$set(element, 'stepValue', 20)
this.$set(element, 'defindTime', [])
}
}
}
</script>

View File

@ -0,0 +1,50 @@
<template>
<el-row :gutter="5">
<el-col :span="12" v-for="chart in typeData" :key="chart.value">
<chart-box :params-data="chart" :item-data="dashboradData[chart.value]"></chart-box>
</el-col>
</el-row>
</template>
<script>
import chartBox from 'views/components/chartBox.vue'
export default {
components: { chartBox },
props: {
detailId: {
type: Number
},
identifier: {
type: String
},
hostName: {
type: String
}
},
data() {
return {
typeData: [
{
title: '内存利用率',
value: 'usage',
expr: JSON.stringify(['round(bocloud_cloudtower_vm_elf_vm_memory_usage_percent{id="' + this.detailId + '"}, 0.01)']),
name: "['内存利用率']",
unit: '%'
}
],
dashboradData: {
usage: {}
}
}
},
methods: {},
created() {
for (const key in this.dashboradData) {
const element = this.dashboradData[key]
this.$set(element, 'step', null)
this.$set(element, 'stepValue', 20)
this.$set(element, 'defindTime', [])
}
},
beforeDestroy() {}
}
</script>

View File

@ -0,0 +1,41 @@
<template>
<el-row :gutter="20">
<el-col :span="12" v-for="chart in typeData" :key="chart.value">
<chart-box :params-data="chart" :item-data="dashboradData[chart.value]"></chart-box>
</el-col>
</el-row>
</template>
<script>
import chartBox from 'views/components/chartBox.vue'
export default {
components: { chartBox },
props: {
detailId: {
type: Number
},
detailName: {
type: String
}
},
data() {
return {
typeData: [
{ title: '网络发送速率', value: 'read', expr: JSON.stringify(['round(bocloud_cloudtower_vm_elf_vm_network_transmit_speed_bps{id="' + this.detailId + '"}, 0.01)']), name: "['网络发送速率']", unit: 'bitps' },
{ title: '网络接收速率', value: 'write', expr: JSON.stringify(['round(bocloud_cloudtower_vm_elf_vm_network_receive_speed_bps{id="' + this.detailId + '"}, 0.01)']), name: "['网络接收速率']", unit: 'bitps' }
],
dashboradData: {
read: {},
write: {}
}
}
},
created() {
for (const key in this.dashboradData) {
const element = this.dashboradData[key]
this.$set(element, 'step', null)
this.$set(element, 'stepValue', 20)
this.$set(element, 'defindTime', [])
}
}
}
</script>

View File

@ -0,0 +1,151 @@
<template>
<div>
<detail-map :detail="detailData" :list="detailMapList" v-if="isShow"></detail-map>
<el-row :gutter="5">
<el-col :span="24">
<el-col :span="12">
<el-card class="box-card m-t-xs" style="height: 300px">
<div slot="header" class="clearfix">
<span>使用情况</span>
</div>
<div class="text-center">
<el-col :span="12">
<div>CPU利用率</div>
<gauge-charts v-if="dashboardData.cpuUsage1" height="190px" id="cpuUsage" width="100%" :data="dashboardData.cpuUsage1"></gauge-charts>
</el-col>
<el-col :span="12">
<div>内存利用率</div>
<gauge-charts v-if="dashboardData.memUsage1" height="190px" id="memUsage" width="100%" :data="dashboardData.memUsage1"></gauge-charts>
</el-col>
</div>
</el-card>
</el-col>
<el-col :span="12" v-for="chart in typeData" :key="chart.value">
<chart-box :params-data="chart" :item-data="dashboardDataChart[chart.value]"></chart-box>
</el-col>
</el-col>
</el-row>
</div>
</template>
<script>
import chartBox from 'views/components/chartBox.vue'
import detailMap from 'views/components/detailMap.vue'
import { getHostDashboard } from 'services/monitor'
import { detailVm } from 'services/platform/index'
export default {
components: {
chartBox,
detailMap
},
props: {
detailId: {
type: Number
},
identifier: {
type: String
},
hostName: {
type: String
},
isShow: {
type: Boolean
}
},
beforeDestroy() {
clearInterval(this.timeIntervalDashboard)
},
data() {
return {
typeData: [
{
title: 'CPU利用率',
value: 'cpu',
expr: JSON.stringify(['round(bocloud_cloudtower_vm_elf_vm_cpu_overall_usage_percent{id="' + this.detailId + '"}, 0.01)']),
name: '["CPU利用率"]',
unit: '%'
},
{
title: '内存利用率',
value: 'mem',
expr: JSON.stringify(['round(bocloud_cloudtower_vm_elf_vm_memory_usage_percent{id="' + this.detailId + '"}, 0.01)']),
name: '["内存利用率"]',
unit: '%'
}
],
dashboardDataChart: {
cpu: {},
mem: {},
read: {}
},
detailData: {},
detailMapList: [
// { name: '', value: 'name', unit: '' },
{ name: 'IP', value: 'managerIp', unit: '' },
{ name: '规格', value: 'spec' },
{ name: '创建时间', value: 'gmtCreate', unit: '' },
{ name: '操作系统', value: 'osCategory' }
],
dashboardData: {},
timeIntervalDashboard: ''
}
},
methods: {
getDetail() {
detailVm(this.detailId).then((data) => {
if (data.success) {
this.detailData = Object.assign({}, data.data)
this.detailData.privateIps = JSON.parse(this.detailData.privateIps)
this.detailData.spec = (this.detailData.cpu ? this.detailData.cpu : 0) + 'C/' + (this.detailData.memory ? this.detailData.memory : 0) + 'GB/'
}
})
},
getDashboard() {
const expr1 = 'round(bocloud_cloudtower_vm_elf_vm_cpu_overall_usage_percent{id="' + this.detailId + '"}, 0.01)'
const expr2 = 'round(bocloud_cloudtower_vm_elf_vm_memory_usage_percent{id="' + this.detailId + '"}, 0.01)'
getHostDashboard({
expr: expr1,
simple: true
}).then((data) => {
if (data.success) {
this.$set(this.dashboardData, 'cpuUsage1', {
name: 'CPU利用率',
data: { value: data.data, name: '%' },
min: 0,
max: 100
})
}
})
getHostDashboard({
expr: expr2,
simple: true
}).then((data) => {
if (data.success) {
this.$set(this.dashboardData, 'memUsage1', {
name: '内存利用率',
data: { value: data.data, name: '%' },
min: 0,
max: 100
})
}
})
if (this.timeIntervalDashboard) {
clearInterval(this.timeIntervalDashboard)
this.timeIntervalDashboard = ''
}
this.timeIntervalDashboard = setInterval(() => {
this.getDashboard()
}, 60 * 1000)
}
},
created() {
for (const key in this.dashboardDataChart) {
const element = this.dashboardDataChart[key]
this.$set(element, 'step', null)
this.$set(element, 'stepValue', 20)
this.$set(element, 'defindTime', [])
}
this.getDetail()
this.getDashboard()
}
}
</script>

View File

@ -0,0 +1,47 @@
<template>
<el-row :gutter="20">
<el-col :span="12" v-for="chart in typeData" :key="chart.value">
<chart-box :params-data="chart" :item-data="dashboradData[chart.value]"></chart-box>
</el-col>
</el-row>
</template>
<script>
import chartBox from 'views/components/chartBox.vue'
export default {
components: { chartBox },
props: {
detailId: {
type: Number
},
detailName: {
type: String
}
},
data() {
return {
typeData: [
{ title: '磁盘读取速率', value: 'read', expr: JSON.stringify(['round(bocloud_cloudtower_vm_elf_vm_disk_overall_read_iops{id="' + this.detailId + '"}, 0.01)']), name: "['磁盘读取速率']", unit: '%' },
{ title: '磁盘写入速率', value: 'write', expr: JSON.stringify(['round(bocloud_cloudtower_vm_elf_vm_disk_overall_write_iops{id="' + this.detailId + '"}, 0.01)']), name: "['磁盘读取速率']", unit: '%' }
],
detailData: {},
detailMapList: [
{ name: '磁盘总量', value: 'diskCapacity', unit: 'GB' },
{ name: '磁盘使用量', value: 'diskUsed', unit: 'GB' },
{ name: '磁盘空闲量', value: 'diskFree', unit: 'GB' }
],
dashboradData: {
read: {},
write: {}
}
}
},
created() {
for (const key in this.dashboradData) {
const element = this.dashboradData[key]
this.$set(element, 'step', null)
this.$set(element, 'stepValue', 20)
this.$set(element, 'defindTime', [])
}
}
}
</script>

View File

@ -0,0 +1,68 @@
<template>
<el-card>
<el-tabs v-model="activeName" class="m-t-n-md">
<el-tab-pane name="overview" label="资源概览">
<overview ref="overview" v-if="activeName == 'overview'" :detail-id="detailId" :identifier="identifier" :host-name="hostName" :is-show="isShow"></overview>
</el-tab-pane>
<el-tab-pane name="cpu" label="CPU">
<cpu ref="cpu" v-if="activeName == 'cpu'" :detail-id="detailId" :identifier="identifier" :host-name="hostName"></cpu>
</el-tab-pane>
<el-tab-pane name="mem" label="内存">
<mem ref="mem" v-if="activeName == 'mem'" :detail-id="detailId" :identifier="identifier" :host-name="hostName"></mem>
</el-tab-pane>
<el-tab-pane name="storage" label="磁盘">
<storage ref="storage" v-if="activeName == 'storage'" :detail-id="detailId" :detail-name="detailName"></storage>
</el-tab-pane>
<el-tab-pane name="net" label="网络">
<net ref="net" v-if="activeName == 'net'" :detail-id="detailId" :detail-name="detailName"></net>
</el-tab-pane>
</el-tabs>
</el-card>
</template>
<script>
import overview from './vmDetail/overview.vue'
import cpu from './vmDetail/cpu.vue'
import mem from './vmDetail/mem.vue'
import storage from './vmDetail/storage.vue'
import net from './vmDetail/net.vue'
export default {
components: {
overview,
cpu,
mem,
storage,
net
},
props: {
detailId: {
type: Number
},
identifier: {
type: String
},
detailName: {
type: String
},
hostName: {
type: String
},
biosUuid: {
type: String
},
isShow: {
type: Boolean,
default: true
}
},
data() {
return {
activeName: 'overview'
}
},
methods: {},
created() {},
mounted() {}
}
</script>
<style scoped></style>

View File

@ -201,6 +201,39 @@
</el-col>
</el-row>
</div>
<div class="server-body" @click="go(item)" v-if="item.type == 'CLOUDTOWER'">
<el-row>
<el-col :span="12" class="body-left">
<div class="body-left-header">
<img src="/web-common-resource/img/platform/cloudTower.png" alt="" />
</div>
<div class="body-left-body" :class="{ colorRed: item.flag, colorWarn: item.warnFlag }">
{{ platformStatusFilter(item.status) }}
</div>
</el-col>
<el-col :span="12" class="body-right">
<div class="tag-box">
<div class="tag">
<el-col :span="12">宿主机</el-col>
<el-col :span="7" class="tag1">{{ item.hostCount }}</el-col>
<el-col :span="2" :offset="1"></el-col>
<div style="clear: both"></div>
</div>
<div class="tag">
<el-col :span="12">云主机</el-col>
<el-col :span="7" class="tag1">{{ item.instance }}</el-col>
<el-col :span="2" :offset="1"></el-col>
<div style="clear: both"></div>
</div>
<div class="tag">
<el-col :span="12">监控</el-col>
<el-col :span="10" :class="item.isAlarm ? 'tag2' : 'tag3'">{{ item.isAlarm ? '已开启' : '已关闭' }}</el-col>
<div style="clear: both"></div>
</div>
</div>
</el-col>
</el-row>
</div>
<div class="server-body" @click="go(item)" v-if="item.type == 'TIANYI' || item.type == 'HUAWEI'">
<el-row>
<el-col :span="12" class="body-left">
@ -403,6 +436,16 @@ export default {
}
})
break
case 'CLOUDTOWER':
this.$router.push({
name: 'MonitorCloudCloudTower',
query: {
vendorId: item.id,
vendorName: item.name,
type: item.type
}
})
break
case 'SMARTX':
this.$router.push({
name: 'MonitorCloudSmart',
@ -518,7 +561,7 @@ export default {
conditionCloudVendor({
condition: JSON.stringify({
condition: 'listByTypes',
types: ['OPENSTACK', 'VMWARE', 'FUSIONCLOUD', 'HMC', 'MANAGEONE', 'KUBERNETES', 'TIANYI', 'HUAWEI', 'H3C', 'ALIYUN', 'SMARTX']
types: ['OPENSTACK', 'VMWARE', 'FUSIONCLOUD', 'HMC', 'MANAGEONE', 'KUBERNETES', 'TIANYI', 'HUAWEI', 'H3C', 'ALIYUN', 'SMARTX', 'CLOUDTOWER']
})
}).then((data) => {
if (data.success) {

View File

@ -0,0 +1,46 @@
<template>
<div class="wrapper-container">
<common-detail :title="$route.query.name" @goBack="goBack">
<div slot="custom_content">
<detail :detail-id="detailId" :detail-name="detailData.name"></detail>
</div>
</common-detail>
</div>
</template>
<script>
import detail from '../cloudTower/host_detail.vue'
export default {
components: {
detail
},
data () {
return {
detailData: {
name: this.$route.query.name
},
detailId: Number(this.$route.query.id),
vendorId: this.$route.query.vendorId
}
},
methods: {
goBack () {
if (!this.vendorId) {
history.go(-1)
} else {
this.$router.push({
name: 'MonitorDashboard',
query: {
vendorId: this.vendorId
}
})
}
}
},
created () {
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,47 @@
<template>
<div class="wrapper-container">
<common-detail :title="$route.query.name" @goBack="goBack">
<div slot="custom_content">
<detail :detail-id="detailId" :instanceId="identifier"></detail>
</div>
</common-detail>
</div>
</template>
<script>
import detail from '../cloudTower/vm_detail.vue'
export default {
components: {
detail
},
data () {
return {
detailData: {
name: this.$route.query.name
},
detailId: Number(this.$route.query.id),
identifier: this.$route.query.identifier,
vendorId: this.$route.query.vendorId
}
},
methods: {
goBack () {
if (!this.vendorId) {
history.go(-1)
} else {
this.$router.push({
name: 'MonitorDashboard',
query: {
vendorId: this.vendorId
}
})
}
}
},
created () {
}
}
</script>
<style scoped>
</style>

View File

@ -54,8 +54,8 @@
<div v-else-if="record.vendorType == 'JDCLOUD'">
<div v-for="(item, index) in record.privateIps" :key="index">(){{ item }}</div>
</div>
<div v-else-if="record.vendorType == 'SMARTX'">
{{ record.managerIp }}
<div v-else-if="record.vendorType == 'SMARTX' || record.vendorType == 'CLOUDTOWER'">
<div>{{ record.managerIp ? '(内网)' + record.managerIp : '--' }}</div>
</div>
<div v-else>
<div v-for="item in record.privateIps" :key="item">(){{ item }}</div>
@ -128,6 +128,7 @@
<vcenter-detail v-if="detailData.vendorType == 'VMWARE'" :detail-id="detailId" :identifier="identifier" :host-name="hostName" :bios-uuid="biosUuid"></vcenter-detail>
<huawei-detail v-if="detailData.vendorType == 'HUAWEI'" :detail-id="detailId" :instance-id="instanceId"></huawei-detail>
<smart-detail v-if="detailData.vendorType == 'SMARTX'" :detail-id="detailId" :instanceId="instanceId"></smart-detail>
<cloudtower-detail v-if="detailData.vendorType == 'CLOUDTOWER'" :detail-id="detailId" :instanceId="instanceId"></cloudtower-detail>
</div>
</common-detail>
</el-card>
@ -144,6 +145,7 @@ import openstackDetail from './cloud/openstack/vm_detail.vue'
import vcenterDetail from './cloud/vcenter/vm_detail.vue'
import huaweiDetail from './cloud/huawei/detail.vue'
import smartDetail from './cloud/smart/vm_detail.vue'
import cloudtowerDetail from './cloud/cloudTower/vm_detail.vue'
import { customColorMethod, handleStart } from 'views/data'
import addPolicy from 'views/components/linkPolicy'
import { downloadFile } from 'utils/index'
@ -214,7 +216,8 @@ export default {
vcenterDetail,
huaweiDetail,
smartDetail,
addPolicy
addPolicy,
cloudtowerDetail
},
data() {
return {
@ -373,7 +376,7 @@ export default {
conditionCloudVendor({
condition: JSON.stringify({
condition: 'listByTypes',
types: ['OPENSTACK', 'VMWARE', 'FUSIONCLOUD', 'HMC', 'MANAGEONE', 'TIANYI', 'HUAWEI', 'H3C', 'ALIYUN', 'QCLOUD', 'AZURE', 'TENCENT', 'AWS', 'SMARTX']
types: ['OPENSTACK', 'VMWARE', 'FUSIONCLOUD', 'HMC', 'MANAGEONE', 'TIANYI', 'HUAWEI', 'H3C', 'ALIYUN', 'QCLOUD', 'AZURE', 'TENCENT', 'AWS', 'SMARTX', 'CLOUDTOWER']
})
}).then((data) => {
if (data.success) {

View File

@ -19,6 +19,21 @@ export const catalogList = [
}
]
},
{
name: 'CloudTower',
value: 'MONITOR_CLOUDTOWER',
vendorType: 'CLOUDTOWER',
data: [
{
name: '宿主机',
value: 'MONITOR_CLOUDTOWER_HOST'
},
{
name: '云主机',
value: 'MONITOR_CLOUDTOWER_VM'
}
]
},
{
name: 'OpenStack',
value: 'MONITOR_OPENSTACK',
@ -334,6 +349,16 @@ export const resourceList = [
value: 'MONITOR_SMARTX_HOST',
type: 'SMARTX'
},
{
name: 'CloudTower宿主机',
value: 'MONITOR_CLOUDTOWER_HOST',
type: 'CLOUDTOWER'
},
{
name: 'CloudTower云主机',
value: 'MONITOR_CLOUDTOWER_VM',
type: 'CLOUDTOWER'
},
{
name: 'Dell存储设备',
value: 'MONITOR_STORAGE_DELL_STORAGE',
@ -664,5 +689,5 @@ export function handleStart(self, data, resourceType) {
}
})
})
.catch(() => {})
.catch(() => { })
}

View File

@ -7,8 +7,8 @@ function resolve(dir) {
return path.join(__dirname, dir)
}
const httpType = 'http://'
const proxyUrl = '23.33.3.3:60006/' // 代理地址设置
const httpType = 'https://'
const proxyUrl = '23.33.3.28:60006/' // 代理地址设置
export default defineConfig({
resolve: {

View File

@ -9,8 +9,8 @@ const CompressPlugin = require('compress-webpack-plugin')
function resolve(dir) {
return path.join(__dirname, dir)
}
const httpType = 'http://'
const proxyUrl = '23.33.3.3:60006/' // 代理地址设置
const httpType = 'https://'
const proxyUrl = '23.33.3.28:60006/' // 代理地址设置
// const proxyUrl = '10.20.51.92:7001' // 代理地址设置
// const proxyUrl = '10.10.2.60:50006/' 苏州代理地址
const publicPath = process.env.NODE_ENV === 'production' ? '/cms-web/' : '/'