【web】 异常预警对接

dev
Wangxin 9 months ago
parent 55d93dfe66
commit 9dfe27a026
  1. 26
      ALOps_sys_fe/alops-ui/src/api/device/files.js
  2. 2
      ALOps_sys_fe/alops-ui/src/api/inMonitoring/devicesState.js
  3. 2
      ALOps_sys_fe/alops-ui/src/router/index.js
  4. 160
      ALOps_sys_fe/alops-ui/src/views/dashboard/PieChart.vue
  5. 11
      ALOps_sys_fe/alops-ui/src/views/device/deviceInformation/index.vue
  6. 163
      ALOps_sys_fe/alops-ui/src/views/device/files/index.vue
  7. 34
      ALOps_sys_fe/alops-ui/src/views/inMonitoring/devicesState/cardItem.vue
  8. 147
      ALOps_sys_fe/alops-ui/src/views/inMonitoring/devicesState/detail.vue
  9. 10
      ALOps_sys_fe/alops-ui/src/views/inMonitoring/devicesState/index.vue
  10. 2
      ALOps_sys_fe/alops-ui/src/views/inMonitoring/inMonitor/message/index.vue
  11. 96
      ALOps_sys_fe/alops-ui/src/views/inMonitoring/inMonitor/rules/index.vue
  12. 117
      ALOps_sys_fe/alops-ui/src/views/index.vue

@ -19,6 +19,32 @@ export function list(query) {
}) })
} }
// 查询设备类型列表
export function deviceTypeList(query) {
return request({
url: 'device/deviceType/query',
method: 'get',
params: query
})
}
// 查询设备厂商列表
export function deviceManuList(query) {
return request({
url: 'device/deviceManu/query',
method: 'get',
params: query
})
}
// 查询设备供应商列表
export function supplierList(query) {
return request({
url: 'device/supplier/query',
method: 'get',
params: query
})
}
// 查询详细 // 查询详细
export function getInfo(id) { export function getInfo(id) {
return request({ return request({

@ -5,7 +5,7 @@ const api = '/device/files/'
// 查询多台设备列表 // 查询多台设备列表
export function list(query) { export function list(query) {
return request({ return request({
url: api + 'list', url: api + 'monitorById',
method: 'get', method: 'get',
params: query params: query
}) })

@ -99,7 +99,7 @@ export const dynamicRoutes = [
permissions: ['inMonitoring:devicesState:edit'], permissions: ['inMonitoring:devicesState:edit'],
children: [ children: [
{ {
path: 'detail/:userId', path: 'detail/:id',
component: () => import('@/views/inMonitoring/devicesState/detail'), component: () => import('@/views/inMonitoring/devicesState/detail'),
name: 'DevicesStateDetail', name: 'DevicesStateDetail',
meta: { title: '设备详情', activeMenu: '/inMonitoring/devicesState-detail' } meta: { title: '设备详情', activeMenu: '/inMonitoring/devicesState-detail' }

File diff suppressed because one or more lines are too long

@ -17,7 +17,7 @@
</el-form-item> </el-form-item>
</el-row> </el-row>
<el-row v-show="queryParams.ruleType == 0"> <el-row v-if="queryParams.ruleType == 0">
<el-col :span="24"> <el-col :span="24">
<el-form-item label="采集频率" prop="frequency"> <el-form-item label="采集频率" prop="frequency">
<el-input-number v-model="queryParams.frequency" controls-position="right" :min="1"></el-input-number> <el-input-number v-model="queryParams.frequency" controls-position="right" :min="1"></el-input-number>
@ -39,7 +39,7 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row v-show="queryParams.ruleType == 1"> <el-row v-if="queryParams.ruleType == 1">
<el-col :span="24"> <el-col :span="24">
<el-form-item label="采集时间限制"> <el-form-item label="采集时间限制">
<el-date-picker <el-date-picker
@ -112,12 +112,8 @@ export default {
// //
rules: { rules: {
userName: [
{ required: true, message: "用户名称不能为空", trigger: "blur" },
{ min: 2, max: 20, message: '用户名称长度必须介于 2 和 20 之间', trigger: 'blur' }
],
dateRange: [ dateRange: [
{ required: true, message: "用户昵称不能为空", trigger: "blur" } { required: true, message: "采集时间不能为空", trigger: "blur" }
], ],
} }
} }
@ -154,7 +150,6 @@ export default {
}) })
}, },
handleDateRangeChange(value) { handleDateRangeChange(value) {
console.log("%c 🐁: handleDateRangeChange -> value ", "font-size:16px;background-color:#dbe986;color:black;", value)
this.queryParams.startTime = value[0] this.queryParams.startTime = value[0]
this.queryParams.endTime = value[1] this.queryParams.endTime = value[1]
}, },

@ -45,7 +45,7 @@
width="60" width="60"
type="index" type="index"
></el-table-column> ></el-table-column>
<el-table-column label="设备ID" align="center" key="equNumber" prop="equNumber" /> <el-table-column label="设备编号" align="center" key="equNumber" prop="equNumber" />
<el-table-column label="设备名称" align="center" key="name" prop="name" :show-overflow-tooltip="true" /> <el-table-column label="设备名称" align="center" key="name" prop="name" :show-overflow-tooltip="true" />
<el-table-column label="设备版本" align="center" key="version" prop="version" :show-overflow-tooltip="true" /> <el-table-column label="设备版本" align="center" key="version" prop="version" :show-overflow-tooltip="true" />
<el-table-column label="设备类型" align="center" key="equType" prop="equType" :show-overflow-tooltip="true" /> <el-table-column label="设备类型" align="center" key="equType" prop="equType" :show-overflow-tooltip="true" />
@ -56,7 +56,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="带外管理IP" align="center" key="ip" prop="ip" width="120" /> <el-table-column label="带外管理IP" align="center" key="ip" prop="ip" width="120" />
<el-table-column label="安装位置" align="center" key="location" prop="Location" width="120" /> <el-table-column label="安装位置" align="center" key="location" prop="location" width="120" />
<el-table-column label="安装时间" align="center" prop="installDate" width="160"> <el-table-column label="安装时间" align="center" prop="installDate" width="160">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.installDate) }}</span> <span>{{ parseTime(scope.row.installDate) }}</span>
@ -67,11 +67,10 @@
<el-table-column label="设备供应商" align="center" key="supplierName" prop="supplierName" width="120" /> <el-table-column label="设备供应商" align="center" key="supplierName" prop="supplierName" width="120" />
<el-table-column label="设备管理员" align="center" key="inCharge" prop="inCharge" width="120" /> <el-table-column label="设备管理员" align="center" key="inCharge" prop="inCharge" width="120" />
<el-table-column label="预计年限" align="center" key="lifeCycle" prop="lifeCycle" width="120" /> <el-table-column label="预计年限" align="center" key="lifeCycle" prop="lifeCycle" width="120" />
<el-table-column label="服役年限" align="center" key="serviceTime" prop="serviceTime" width="120" />
<el-table-column label="质保时间" align="center" key="warranty" prop="warranty" width="120" /> <el-table-column label="质保时间" align="center" key="warranty" prop="warranty" width="120" />
<el-table-column label="设备图片" align="center" key="image" prop="image" :show-overflow-tooltip="true" > <el-table-column label="设备图片" align="center" key="equImage" prop="equImage" :show-overflow-tooltip="true" >
<template slot-scope="scope"> <template slot-scope="scope">
<ImagePreview :src="scope.row.image"/> <ImagePreview :src="scope.row.equImage"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="设备添加人" align="center" key="createBy" prop="createBy" width="120" /> <el-table-column label="设备添加人" align="center" key="createBy" prop="createBy" width="120" />
@ -113,15 +112,28 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="设备类型" prop="equType"> <el-form-item label="设备类型" prop="equTypeId">
<el-input v-model="form.equType" placeholder="请输入设备类型" maxlength="30" /> <el-select
v-model="form.equTypeId"
filterable
clearable
remote
reserve-keyword
placeholder="请输入"
:remote-method="remoteMethod1"
:loading="loading1">
<el-option
v-for="item in options1"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="设备级别" prop="deviceLevel"> <el-form-item label="设备级别" prop="deviceLevel">
<el-select v-model="form.deviceLevel" placeholder="设备级别" clearable style="width: 240px"> <el-input v-model="form.deviceLevel" placeholder="请输入设备级别" maxlength="30" />
<el-option v-for="dict in dict.type.warning_level" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
@ -130,8 +142,43 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="设备厂商" prop="manufacture"> <el-form-item label="设备厂商" prop="equManuId">
<el-input v-model="form.manufacture" placeholder="请输入设备厂商" maxlength="30" /> <el-select
v-model="form.equManuId"
filterable
clearable
remote
reserve-keyword
placeholder="请输入"
:remote-method="remoteMethod2"
:loading="loading2">
<el-option
v-for="item in options2"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="设备供应商" prop="supplierId">
<el-select
v-model="form.supplierId"
filterable
clearable
remote
reserve-keyword
placeholder="请输入"
:remote-method="remoteMethod3"
:loading="loading3">
<el-option
v-for="item in options3"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
@ -149,11 +196,6 @@
<el-input v-model="form.lifeCycle" placeholder="请输入预计年限" maxlength="30" /> <el-input v-model="form.lifeCycle" placeholder="请输入预计年限" maxlength="30" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12">
<el-form-item label="服役年限" prop="serviceTime">
<el-input v-model="form.serviceTime" placeholder="请输入服役年限" maxlength="30" />
</el-form-item>
</el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="质保年限" prop="warranty"> <el-form-item label="质保年限" prop="warranty">
<el-input v-model="form.warranty" placeholder="请输入质保年限" maxlength="30" /> <el-input v-model="form.warranty" placeholder="请输入质保年限" maxlength="30" />
@ -161,8 +203,8 @@
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="设备图片" prop="image"> <el-form-item label="设备图片" prop="equImage">
<ImageUpload @input="upImage" :value="form.image"/> <ImageUpload @input="upImage" :value="form.equImage"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@ -198,7 +240,7 @@
</template> </template>
<script> <script>
import { getDict, list, getInfo, del, add, update } from "@/api/device/files" import { list, del, add, update, deviceTypeList, deviceManuList, supplierList } from "@/api/device/files"
import { getToken } from "@/utils/auth" import { getToken } from "@/utils/auth"
import Treeselect from "@riophae/vue-treeselect" import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css" import "@riophae/vue-treeselect/dist/vue-treeselect.css"
@ -213,6 +255,13 @@ export default {
return { return {
// //
loading: true, loading: true,
loading1: true,
loading2: true,
loading3: true,
options1: [],
options2: [],
options3: [],
// //
ids: [], ids: [],
// //
@ -282,7 +331,7 @@ export default {
version: [ version: [
{ required: true, message: "设备版本不能为空", trigger: "blur" }, { required: true, message: "设备版本不能为空", trigger: "blur" },
], ],
equType: [ equTypeId: [
{ required: true, message: "设备类型不能为空", trigger: "blur" } { required: true, message: "设备类型不能为空", trigger: "blur" }
], ],
deviceLevel: [ deviceLevel: [
@ -291,9 +340,12 @@ export default {
ip: [ ip: [
{ required: true, message: "带外管理IP不能为空", trigger: "blur" } { required: true, message: "带外管理IP不能为空", trigger: "blur" }
], ],
manufacture: [ equManuId: [
{ required: true, message: "设备厂商不能为空", trigger: "blur" }, { required: true, message: "设备厂商不能为空", trigger: "blur" },
], ],
supplierId: [
{ required: true, message: "设备供应商不能为空", trigger: "blur" },
],
location: [ location: [
{ required: true, message: "安装位置不能为空", trigger: "blur" } { required: true, message: "安装位置不能为空", trigger: "blur" }
], ],
@ -303,13 +355,10 @@ export default {
lifeCycle: [ lifeCycle: [
{ required: true, message: "预计年限不能为空", trigger: "blur" } { required: true, message: "预计年限不能为空", trigger: "blur" }
], ],
serviceTime: [
{ required: true, message: "服役年限不能为空", trigger: "blur" },
],
warranty: [ warranty: [
{ required: true, message: "质保年限不能为空", trigger: "blur" } { required: true, message: "质保年限不能为空", trigger: "blur" }
], ],
image: [ equImage: [
{ required: true, message: "设备图片不能为空", trigger: "blur" } { required: true, message: "设备图片不能为空", trigger: "blur" }
], ],
} }
@ -323,6 +372,10 @@ export default {
}, },
created() { created() {
this.getList() this.getList()
this.getDeviceTypeList()
this.getDeviceManuList()
this.getSupplierList()
}, },
methods: { methods: {
/** 查询设备列表 */ /** 查询设备列表 */
@ -335,9 +388,63 @@ export default {
} }
) )
}, },
getDeviceTypeList(query) {
deviceTypeList({name:query}).then(response => {
this.options1 = response.rows
this.loading1 = false
}
)
},
remoteMethod1(query) {
if (query !== '') {
this.loading1 = true;
setTimeout(() => {
this.loading = false;
this.getDeviceTypeList(query)
}, 200);
} else {
this.options1 = [];
}
},
getDeviceManuList(query) {
deviceManuList({name:query}).then(response => {
this.options2 = response.rows
this.loading2 = false
}
)
},
remoteMethod2(query) {
if (query !== '') {
this.loading2 = true;
setTimeout(() => {
this.loading = false;
this.getDeviceManuList(query)
}, 200);
} else {
this.options2 = [];
}
},
getSupplierList(query) {
supplierList({name:query}).then(response => {
this.options3 = response.rows
this.loading3 = false
}
)
},
remoteMethod3(query) {
if (query !== '') {
this.loading3 = true;
setTimeout(() => {
this.loading = false;
this.getSupplierList(query)
}, 200);
} else {
this.options3 = [];
}
},
upImage(fileList){ upImage(fileList){
console.log(fileList) console.log(fileList)
this.form.image = fileList this.form.equImage = fileList
}, },
// //
cancel() { cancel() {
@ -415,7 +522,7 @@ export default {
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const Ids = row.id || this.ids const Ids = row.id || this.ids
this.$modal.confirm('是否确认删除设备ID为"' + Ids + '"的数据项?').then(function() { this.$modal.confirm('是否确认删除设备编号为"' + Ids + '"的数据项?').then(function() {
return del(Ids) return del(Ids)
}).then(() => { }).then(() => {
this.getList() this.getList()

@ -10,39 +10,41 @@
<i class="fas fa-network-wired"></i> <i class="fas fa-network-wired"></i>
{{cardData.name}} {{cardData.name}}
</h2> </h2>
<span class="status-badge status-online"> <span class="status-badge " :class="cardData.status ? 'status-online' : 'status-danger'">
<i class="fas fa-circle"></i> 在线 <i class="fas fa-circle"></i>
{{ cardData.status ? '正常' : '停用' }}
</span> </span>
</div> </div>
<div class="device-box"> <div class="device-box">
<div class="device-image"> <div class="device-image">
<i class="fas fa-server"></i> <img v-if="cardData.image" :src="cardData.image" alt="" class="device-icon">
<i v-else class="fas fa-server"></i>
</div> </div>
<div class="device-info"> <div class="device-info">
<div class="info-item"> <div class="info-item">
<span class="info-label"> <span class="info-label">
<i class="fas fa-layer-group"></i> 设备级别 <i class="fas fa-layer-group"></i> 设备级别
</span> </span>
<span class="info-value">A</span> <span class="info-value">{{cardData.deviceLevel || '暂无'}}</span>
</div> </div>
<div class="info-item"> <div class="info-item">
<span class="info-label"> <span class="info-label">
<i class="fas fa-map-marker-alt"></i> 安装位置 <i class="fas fa-map-marker-alt"></i> 安装位置
</span> </span>
<span class="info-value">一层</span> <span class="info-value">{{cardData.location || '暂无'}}</span>
</div> </div>
<div class="info-item"> <div class="info-item">
<span class="info-label"> <span class="info-label">
<i class="fas fa-tag"></i> 品牌型号 <i class="fas fa-tag"></i> 品牌型号
</span> </span>
<span class="info-value">Cisco</span> <span class="info-value">{{cardData.manufacture || '暂无'}}</span>
</div> </div>
<div class="info-item"> <div class="info-item">
<span class="info-label"> <span class="info-label">
<i class="fas fa-heartbeat"></i> 运行状态 <i class="fas fa-heartbeat"></i> 带外IP
</span> </span>
<span class="info-value">运行正常</span> <span class="info-value">{{cardData.ip || '暂无'}}</span>
</div> </div>
</div> </div>
</div> </div>
@ -50,28 +52,28 @@
<div class="metrics-grid"> <div class="metrics-grid">
<div class="metric-card"> <div class="metric-card">
<div class="metric-value cpu-usage">66%</div> <div class="metric-value cpu-usage">{{cardData.cpuUtilization||0}}%</div>
<div class="metric-label">CPU占用</div> <div class="metric-label">CPU占用</div>
<div class="progress-bar"> <div class="progress-bar">
<div class="progress-fill" style="width: 66%"></div> <div class="progress-fill" :style="{width: cardData.cpuUtilization||0+'%'}"></div>
</div> </div>
</div> </div>
<div class="metric-card"> <div class="metric-card">
<div class="metric-value cpu-usage">66%</div> <div class="metric-value cpu-usage">{{cardData.contWorkPeriod||0}}%</div>
<div class="metric-label">内存占用</div> <div class="metric-label">内存占用</div>
<div class="progress-bar"> <div class="progress-bar">
<div class="progress-fill" style="width: 66%"></div> <div class="progress-fill" :style="{width: cardData.contWorkPeriod||0+'%'}"></div>
</div> </div>
</div> </div>
<div class="metric-card"> <div class="metric-card">
<div class="metric-value alert-pending">待开发</div> <div class="metric-value alert-pending">{{cardData.unhandledAlertCount||0}}</div>
<div class="metric-label">待处理预警数</div> <div class="metric-label">待处理预警数</div>
</div> </div>
<div class="metric-card"> <div class="metric-card">
<div class="metric-value alert-total">待开发</div> <div class="metric-value alert-total">{{cardData.handledAlertCount||0}}</div>
<div class="metric-label">预警总数</div> <div class="metric-label">预警总数</div>
</div> </div>
</div> </div>
@ -353,6 +355,10 @@ export default {
overflow: hidden; overflow: hidden;
border: 1px solid rgba(226, 232, 240, 0.8); border: 1px solid rgba(226, 232, 240, 0.8);
} }
.device-icon{
max-width: 100%;
height: auto;
}
.device-image i { .device-image i {
font-size: 80px; font-size: 80px;

@ -7,130 +7,141 @@
<div class="card-header"> <div class="card-header">
<h2 class="card-title"> <h2 class="card-title">
<i class="fas fa-network-wired"></i> <i class="fas fa-network-wired"></i>
设备概览 {{details.name}}
</h2> </h2>
<span class="status-badge status-online"> <span class="status-badge " :class="details.status ? 'status-online' : 'status-danger'">
<i class="fas fa-circle"></i> 在线 <i class="fas fa-circle"></i>
{{ details.status ? '正常' : '停用' }}
</span> </span>
</div> </div>
<div class="top-section-con"> <div class="top-section-con">
<div class="device-image"> <div class="device-image">
<i class="fas fa-server"></i> <img v-if="details.image" :src="details.image" alt="" class="device-icon">
<i v-else class="fas fa-server"></i>
</div> </div>
<!-- 设备基本信息 --> <!-- 设备基本信息 -->
<div class="device-info"> <div class="device-info">
<div class="info-title">设备基本信息</div> <div class="info-title">设备基本信息</div>
<div class="info-item"> <div class="info-item">
<span class="info-label"> <span class="info-label">
<i class="fas fa-layer-group"></i> 设备级别 <i class="fas fa-heartbeat"></i> 设备编号
</span> </span>
<span class="info-value">A级</span> <span class="info-value">{{details.id || '暂无'}}</span>
</div> </div>
<div class="info-item"> <div class="info-item">
<span class="info-label"> <span class="info-label">
<i class="fas fa-map-marker-alt"></i> 安装位置 <i class="fas fa-layer-group"></i> 固件版本
</span> </span>
<span class="info-value">数据中心-主柜</span> <span class="info-value">{{details.version || '暂无'}}</span>
</div> </div>
<div class="info-item"> <div class="info-item">
<span class="info-label"> <span class="info-label">
<i class="fas fa-tag"></i> 品牌型号 <i class="fas fa-layer-group"></i> 设备级别
</span>
<span class="info-value">{{details.deviceLevel || '暂无'}}</span>
</div>
<div class="info-item">
<span class="info-label">
<i class="fas fa-map-marker-alt"></i> 安装位置
</span> </span>
<span class="info-value">Cisco</span> <span class="info-value">{{details.location || '暂无'}}</span>
</div> </div>
<div class="info-item"> <div class="info-item">
<span class="info-label"> <span class="info-label">
<i class="fas fa-heartbeat"></i> 运行状态 <i class="fas fa-tag"></i> 品牌型号
</span> </span>
<span class="info-value">运行正常</span> <span class="info-value">{{details.manufacture || '暂无'}}</span>
</div> </div>
</div> </div>
<!-- 设备基本信息 --> <!-- 设备出厂信息 -->
<div class="device-info"> <div class="device-info">
<div class="info-title">设备基本信息</div> <div class="info-title">设备出厂信息</div>
<div class="info-item"> <div class="info-item">
<span class="info-label"> <span class="info-label">
<i class="fas fa-layer-group"></i> 设备级别 <i class="fas fa-layer-group"></i> 生产厂商名称
</span> </span>
<span class="info-value">A级</span> <span class="info-value">{{details.manufacture || '暂无'}}</span>
</div> </div>
<div class="info-item"> <div class="info-item">
<span class="info-label"> <span class="info-label">
<i class="fas fa-map-marker-alt"></i> 安装位置 <i class="fas fa-map-marker-alt"></i> 供货商名称
</span> </span>
<span class="info-value">数据中心-主柜</span> <span class="info-value">{{details.supplierName || '暂无'}}</span>
</div> </div>
<div class="info-item"> <div class="info-item">
<span class="info-label"> <span class="info-label">
<i class="fas fa-tag"></i> 品牌型号 <i class="fas fa-tag"></i> 供货商联系人
</span> </span>
<span class="info-value">Cisco</span> <span class="info-value">{{ '无字段'}}</span>
</div> </div>
<div class="info-item"> <div class="info-item">
<span class="info-label"> <span class="info-label">
<i class="fas fa-heartbeat"></i> 运行状态 <i class="fas fa-heartbeat"></i> 供货商联系电话
</span> </span>
<span class="info-value">运行正常</span> <span class="info-value">{{ '无字段'}}</span>
</div>
<div class="info-item">
<span class="info-label">
<i class="fas fa-heartbeat"></i> 质保时间
</span>
<span class="info-value">{{details.warranty || '暂无'}}</span>
</div> </div>
</div> </div>
<!-- 设备基本信息 --> <!-- 设备管理信息 -->
<div class="device-info"> <div class="device-info">
<div class="info-title">设备基本信息</div> <div class="info-title">设备基本信息</div>
<div class="info-item"> <div class="info-item">
<span class="info-label"> <span class="info-label">
<i class="fas fa-layer-group"></i> 设备级别 <i class="fas fa-layer-group"></i> 带外管理IP
</span> </span>
<span class="info-value">A级</span> <span class="info-value">{{details.ip || '暂无'}}</span>
</div> </div>
<div class="info-item"> <div class="info-item">
<span class="info-label"> <span class="info-label">
<i class="fas fa-map-marker-alt"></i> 安装位置 <i class="fas fa-layer-group"></i> 安装位置
</span> </span>
<span class="info-value">数据中心-主柜</span> <span class="info-value">{{details.location || '暂无'}}</span>
</div> </div>
<div class="info-item"> <div class="info-item">
<span class="info-label"> <span class="info-label">
<i class="fas fa-tag"></i> 品牌型号 <i class="fas fa-layer-group"></i> 安装日期
</span> </span>
<span class="info-value">Cisco</span> <span class="info-value">{{parseTime(details.installDate) || '暂无'}}</span>
</div> </div>
<div class="info-item"> <div class="info-item">
<span class="info-label"> <span class="info-label">
<i class="fas fa-heartbeat"></i> 运行状态 <i class="fas fa-layer-group"></i> 管理员
</span> </span>
<span class="info-value">运行正常</span> <span class="info-value">{{details.inCharge || '暂无'}}</span>
</div> </div>
</div> </div>
<!-- 设备基本信息 -->
<!-- 设备状态信息 -->
<div class="device-info"> <div class="device-info">
<div class="info-title">设备基本信息</div> <div class="info-title">设备状态信息</div>
<div class="info-item"> <div class="info-item">
<span class="info-label"> <span class="info-label">
<i class="fas fa-layer-group"></i> 设备级别 <i class="fas fa-layer-group"></i> 设备持续运行时长
</span>
<span class="info-value">A级</span>
</div>
<div class="info-item">
<span class="info-label">
<i class="fas fa-map-marker-alt"></i> 安装位置
</span> </span>
<span class="info-value">数据中心-主柜</span> <span class="info-value">{{'无字段'}}</span>
</div> </div>
<div class="info-item"> <div class="info-item">
<span class="info-label"> <span class="info-label">
<i class="fas fa-tag"></i> 品牌型号 <i class="fas fa-layer-group"></i> 待处理预警数
</span> </span>
<span class="info-value">Cisco</span> <span class="info-value">{{details.unhandledAlertCount || '暂无'}}</span>
</div> </div>
<div class="info-item"> <div class="info-item">
<span class="info-label"> <span class="info-label">
<i class="fas fa-heartbeat"></i> 运行状态 <i class="fas fa-layer-group"></i> 预警总数
</span> </span>
<span class="info-value">运行正常</span> <span class="info-value">{{details.handledAlertCount || '暂无'}}</span>
</div> </div>
</div> </div>
</div> </div>
@ -182,6 +193,7 @@
<script> <script>
import { getInfo, historyQuery } from "@/api/inMonitoring/devicesState"
import * as echarts from 'echarts' import * as echarts from 'echarts'
require('echarts/theme/macarons') // echarts theme require('echarts/theme/macarons') // echarts theme
import History from './history.vue' import History from './history.vue'
@ -199,14 +211,25 @@ export default {
{ name: '路由表信息' }, { name: '路由表信息' },
], ],
tabIndex: 0, tabIndex: 0,
details: {},
historyQueryList: {
minTime: '',
maxTime: '',
pageNum: 1,
pageSize: 1000,
},
} }
}, },
mounted() { mounted() {
let routeList = this.$route.params;
this.initCharts(); this.initCharts();
}, this.getInfoFun(routeList.id)
this.gethistoryQuery(routeList.id)
},
methods: { methods: {
initCharts() { initCharts() {
// //
@ -389,7 +412,29 @@ export default {
performanceChart.resize(); performanceChart.resize();
trafficChart.resize(); trafficChart.resize();
}); });
} },
/** 查询设备列表 */
getInfoFun(id) {
this.loading = true
getInfo(id).then(response => {
this.details = response.data
this.loading = false
}
)
},
/** 设备管理基本信息(获取设备指定时间段内的历史监控信息) */
gethistoryQuery(id) {
this.loading = true
let queryForm = {
id: id,
...this.historyQueryList
}
historyQuery(queryForm).then(response => {
this.details = response.data
this.loading = false
}
)
},
} }
} }
@ -542,8 +587,8 @@ export default {
} }
.device-info { .device-info {
display: grid; display: flex;
grid-template-columns: 1fr; flex-direction:column;
gap: 15px; gap: 15px;
} }
@ -557,7 +602,7 @@ export default {
.info-item { .info-item {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: 12px; padding: 8px 12px;
background: rgba(255, 255, 255, 0.7); background: rgba(255, 255, 255, 0.7);
border-radius: 12px; border-radius: 12px;
border: 1px solid rgba(226, 232, 240, 0.8); border: 1px solid rgba(226, 232, 240, 0.8);

@ -5,7 +5,7 @@
<!--设备状态监控=--> <!--设备状态监控=-->
<pane size="84"> <pane size="84">
<el-col> <el-col>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> <!-- <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="设备类型" prop="status"> <el-form-item label="设备类型" prop="status">
<el-select v-model="queryParams.status" placeholder="启用状态" clearable style="width: 240px"> <el-select v-model="queryParams.status" placeholder="启用状态" clearable style="width: 240px">
<el-option v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" /> <el-option v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
@ -34,7 +34,7 @@
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form> -->
<div class="bodyBox" v-loading="loading"> <div class="bodyBox" v-loading="loading">
<el-row :gutter="10"> <el-row :gutter="10">
@ -360,12 +360,6 @@ export default {
this.$refs.tree.setCurrentKey(null) this.$refs.tree.setCurrentKey(null)
this.handleQuery() this.handleQuery()
}, },
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.userId)
this.single = selection.length != 1
this.multiple = !selection.length
},
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd() { handleAdd() {
this.reset() this.reset()

@ -283,7 +283,7 @@ export default {
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const Ids = row.id || this.ids const Ids = row.id || this.ids
this.$modal.confirm('是否确认删除设备ID为"' + Ids + '"的数据项?').then(function() { this.$modal.confirm('是否确认删除设备编号为"' + Ids + '"的数据项?').then(function() {
return del(Ids) return del(Ids)
}).then(() => { }).then(() => {
this.getList() this.getList()

@ -69,7 +69,7 @@
<el-col :span="24"> <el-col :span="24">
<el-form-item label="触发条件" prop="compareValue1"> <el-form-item label="触发条件" prop="compareValue1">
<el-col :span="6"> <el-col :span="6">
<el-select v-model="form.paramName" placeholder="请选择" style="width: 100%"> <el-select v-model="form.paramName" placeholder="请选择" style="width: 100%" @change="byTableDataChange">
<el-option v-for="dict in byTableData" :key="dict.columnName" :label="dict.paramName" :value="dict.columnName"></el-option> <el-option v-for="dict in byTableData" :key="dict.columnName" :label="dict.paramName" :value="dict.columnName"></el-option>
</el-select> </el-select>
</el-col> </el-col>
@ -128,24 +128,6 @@
</el-dialog> </el-dialog>
<!-- 设备导入对话框 -->
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
<el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip">
<div class="el-upload__tip" slot="tip">
<el-checkbox v-model="upload.updateSupport" />是否更新已经存在的设备档案
</div>
<span>仅允许导入xlsxlsx格式文件</span>
<el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate">下载模板</el-link>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm"> </el-button>
<el-button @click="upload.open = false"> </el-button>
</div>
</el-dialog>
</div> </div>
</template> </template>
@ -212,6 +194,8 @@ export default {
}, },
// //
byTableData: [], byTableData: [],
byTableItem: {},
alertWayOptions: [ alertWayOptions: [
{ {
value: 'noemail', value: 'noemail',
@ -317,7 +301,6 @@ export default {
getByTable() { getByTable() {
this.loading = true this.loading = true
byTable().then(response => { byTable().then(response => {
console.log("%c 🇻🇳: getList -> response ", "font-size:16px;background-color:#c9f364;color:black;", response)
this.byTableData = response.data this.byTableData = response.data
this.loading = false this.loading = false
} }
@ -344,6 +327,14 @@ export default {
this.queryParams.pageNum = 1 this.queryParams.pageNum = 1
this.getList() this.getList()
}, },
byTableDataChange(val) {
this.byTableItem = this.byTableData.find(item => item.columnName == val)
this.form.alertRule.tableName = findData.tableName
},
// byTableDataChange(val) {
// let findData = this.waming_rules.find(item => item.columnName == val)
// this.form.tableName = findData.tableName
// },
/** 重置按钮操作 */ /** 重置按钮操作 */
resetQuery() { resetQuery() {
this.dateRange = [] this.dateRange = []
@ -364,38 +355,43 @@ export default {
}, },
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset()
this.form = {...row}
this.open = true this.open = true
this.title = "修改" this.title = "修改设备"
this.reset()
let compareValueData = this.parseCompareValue(row.compareValue)
this.form = {...row,operator:this.unescapeHtml(row.operator),compareValue1:compareValueData[0],compareValue2:compareValueData[1]}
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm: function() { submitForm: function() {
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (valid) { if (valid) {
let form = {...this.form} let form = {...this.form}
this.form.alertRule = { let formData = {}
formData.alertRule = {
id: form.id,
ruleName: form.ruleName, ruleName: form.ruleName,
description: form.description, description: form.description,
alertStation: form.alertStation ? form.alertStation : "", alertStation: form.alertStation ? form.alertStation : "",
alertWay: form.alertWay, alertWay: form.alertWay,
severity: form.severity, severity: form.severity,
tableName: this.byTableItem.tableName,
enable:0 enable:0
} }
this.form.alertRuleConditionList = [{ formData.alertRuleConditionList = [{
paramName: form.paramName, paramName: form.paramName,
compareValue: form.compareValue2?form.compareValue1+','+form.compareValue2:form.compareValue1, compareValue: form.compareValue2?form.compareValue1+','+form.compareValue2:form.compareValue1,
operator: form.operator operator: form.operator,
paramType: this.byTableItem.paramType
}] }]
if (this.form.id != undefined) { if (this.form.id != undefined) {
update(this.form).then(response => { update(formData).then(response => {
this.$modal.msgSuccess("修改成功") this.$modal.msgSuccess("修改成功")
this.open = false this.open = false
this.getList() this.getList()
}) })
} else { } else {
add(this.form).then(response => { add(formData).then(response => {
this.$modal.msgSuccess("新增成功") this.$modal.msgSuccess("新增成功")
this.open = false this.open = false
this.getList() this.getList()
@ -407,7 +403,7 @@ export default {
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const Ids = row.id || this.ids const Ids = row.id || this.ids
this.$modal.confirm('是否确认删除设备ID为"' + Ids + '"的数据项?').then(function() { this.$modal.confirm('是否确认删除设备编号为"' + Ids + '"的数据项?').then(function() {
return del(Ids) return del(Ids)
}).then(() => { }).then(() => {
this.getList() this.getList()
@ -439,7 +435,47 @@ export default {
// //
submitFileForm() { submitFileForm() {
this.$refs.upload.submit() this.$refs.upload.submit()
},
parseCompareValue(value) {
if (!value) return [0, 0];
//
const parts = value.split(/[,;\s]+/);
//
const validNumbers = parts
.map(part => parseInt(part))
.filter(num => !isNaN(num));
if (validNumbers.length === 0) {
return [0, 0];
} else if (validNumbers.length === 1) {
return [validNumbers[0], 0];
} else {
return [validNumbers[0], validNumbers[1]];
} }
},
/**
* 将HTML实体转义为普通字符
*
* @param {string} str - 需要转换的字符串
* @returns {string} 转换后的字符串
*/
unescapeHtml(str){
if (typeof str !== 'string') return str;
const htmlEntities = {
'&amp;': '&',
'&lt;': '<',
'&gt;': '>',
'&quot;': '"',
'&#39;': "'",
'&#x2F;': '/',
'&#x60;': '`',
'&#x3D;': '='
};
return str.replace(/&(amp|lt|gt|quot|#39|#x2F|#x60|#x3D);/g, (match, entity) => {
return htmlEntities[match] || match;
});
}
} }
} }
</script> </script>

@ -19,12 +19,12 @@
<div class="stat-value">{{ alertMessageData.monthCount }}</div> <div class="stat-value">{{ alertMessageData.monthCount }}</div>
</div> </div>
<!-- 等级预警 --> <!-- 等级预警 -->
<div class="stat-card" :class="i.count == 0?'normal':i.count>10?'warning':''" v-for="(i,k) in alertMessageData.levelCount" :key="k"> <div class="stat-card" :class="i.count == 0?'normal':i.count>10?'warning':''" v-for="i in alertMessageData.levelCount" :key="i.id">
<div class="stat-label">{{ `等级${i.level}预警` }}</div> <div class="stat-label">{{ `等级${i.level}预警` }}</div>
<div class="stat-value">{{ i.count }}</div> <div class="stat-value">{{ i.count }}</div>
</div> </div>
<!-- 设备预警 --> <!-- 设备预警 -->
<div class="stat-card" :class="i.count == 0?'normal':i.count>10?'warning':''" v-for="(i,k) in alertMessageData.typeCount" :key="k"> <div class="stat-card" :class="i.count == 0?'normal':i.count>10?'warning':''" v-for="i in alertMessageData.typeCount" :key="i.id">
<div class="stat-label">{{ `${i.name}预警` }}</div> <div class="stat-label">{{ `${i.name}预警` }}</div>
<div class="stat-value">{{ i.count }}</div> <div class="stat-value">{{ i.count }}</div>
</div> </div>
@ -39,18 +39,7 @@
<h2 class="card-title"><i class="fas fa-microchip"></i> 检测设备信息</h2> <h2 class="card-title"><i class="fas fa-microchip"></i> 检测设备信息</h2>
</div> </div>
<ul class="device-list"> <ul class="device-list">
<li class="device-item" v-for="device in devices" :key="device.id" :class="device.status"> <PieChart height="250px" :chartData="byEquTypeData"/>
<div class="device-icon">
<i :class="device.icon"></i>
</div>
<div class="device-info">
<div class="device-name">{{ device.name }}</div>
<div class="device-details">{{ device.description }}</div>
</div>
<span :class="device.status === 'UNHANDLED' ? 'alert-badge' : 'normal-badge'">
{{ device.status === 'UNHANDLED' ? '预警中' : '正常' }}
</span>
</li>
</ul> </ul>
</div> </div>
</div> </div>
@ -61,6 +50,7 @@
<div class="card-header"> <div class="card-header">
<h2 class="card-title"><i class="fas fa-bell"></i> 设备预警信息</h2> <h2 class="card-title"><i class="fas fa-bell"></i> 设备预警信息</h2>
</div> </div>
<el-empty description="暂无预警" v-if="alerts.length == 0"></el-empty>
<ul class="device-list" v-infinite-scroll="loadMore" :infinite-scroll-disabled="isLoading || noMore" infinite-scroll-distance="50" infinite-scroll-delay="300"> <ul class="device-list" v-infinite-scroll="loadMore" :infinite-scroll-disabled="isLoading || noMore" infinite-scroll-distance="50" infinite-scroll-delay="300">
<li class="device-item" v-for="alert in alerts" :key="alert.id" :class="alert.status === 'UNHANDLED' ? 'warning' : 'normal'" > <li class="device-item" v-for="alert in alerts" :key="alert.id" :class="alert.status === 'UNHANDLED' ? 'warning' : 'normal'" >
<div class="device-icon"> <div class="device-icon">
@ -93,7 +83,9 @@
<div class="last-update">最后更新: {{ lastUpdate }}</div> <div class="last-update">最后更新: {{ lastUpdate }}</div>
</div> </div>
<div class="table-container"> <div class="table-container">
<table>
<el-empty description="暂无预警" v-if="tableHeaders.length == 0"></el-empty>
<table v-else>
<thead> <thead>
<tr> <tr>
<th v-for="header in tableHeaders" :key="header">{{ header }}</th> <th v-for="header in tableHeaders" :key="header">{{ header }}</th>
@ -104,22 +96,22 @@
<td>{{ device.name }}</td> <td>{{ device.name }}</td>
<td>{{ device.location }}</td> <td>{{ device.location }}</td>
<td> <td>
<span :class="getCpuStatus(device.cpuUsage)"></span> <span :class="getCpuStatus(device.cpuUtilization || 0)"></span>
{{ device.cpuUsage }}% {{ device.cpuUtilization || 0 }}%
</td> </td>
<td> <td>
<span :class="getMemoryStatus(device.memoryUsage)"></span> <span :class="getMemoryStatus(device.memoryUtilization || 0)"></span>
{{ device.memoryUsage }}% {{ device.memoryUtilization || 0 }}%
</td> </td>
<td>{{ device.temperature }}°C</td> <td>{{ device.temperature || 0 }}°C</td>
<td> <td>
<div class="health-bar"> <div class="health-bar">
<div class="health-fill" :class="getHealthStatus(device.health)"></div> <div class="health-fill" :class="getHealthStatus(device.health || 0)"></div>
</div> </div>
{{ device.health }}% {{ device.health || 0 }}%
</td> </td>
<td>{{ device.uptime }}</td> <td>{{ formatDuration(device.contWorkPeriod) }}</td>
<td>{{ device.collectionTime }}</td> <td>{{ parseTime(device.gatherTime) || '--' }}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -173,56 +165,21 @@ export default {
alerts: [], alerts: [],
// //
alertMessageData: [], alertMessageData: [],
byEquTypeData: [],
tableHeaders: ['设备名称', '设备位置', 'CPU使用率', '内存使用率', '温度', '健康度', '设备运行时长', '采集时间'], tableHeaders: ['设备名称', '设备位置', 'CPU使用率', '内存使用率', '温度', '健康度', '设备运行时长', '采集时间'],
deviceStatus: [ deviceStatus: []
{
id: 1,
name: 'PLC控制系统',
location: '主控室A区',
cpuUsage: 45,
memoryUsage: 62,
temperature: 42,
health: 85,
uptime: '125天8小时',
collectionTime: '2021-10-16 15:20:00'
},
{
id: 2,
name: '数据采集器',
location: '污水处理区',
cpuUsage: 78,
memoryUsage: 85,
temperature: 58,
health: 65,
uptime: '89天12小时',
collectionTime: '2021-10-16 15:22:00'
},
{
id: 3,
name: '监控服务器',
location: '数据中心',
cpuUsage: 32,
memoryUsage: 45,
temperature: 38,
health: 92,
uptime: '210天3小时',
collectionTime: '2021-10-16 15:25:00'
},
{
id: 4,
name: '网络交换机',
location: '通信机房',
cpuUsage: 15,
memoryUsage: 28,
temperature: 35,
health: 95,
uptime: '156天7小时',
collectionTime: '2021-10-16 15:18:00'
}
]
} }
}, },
methods: { methods: {
formatDuration(input) {//
if (typeof input !== 'string') return "0天0小时";
const match = input.match(/(\d+)\s*days?,\s*(\d+):/i);
return match ? `${match[1]}${match[2]}小时` : "0天0小时";
},
getCpuStatus(usage) { getCpuStatus(usage) {
if (usage < 50) return 'status-indicator status-good'; if (usage < 50) return 'status-indicator status-good';
if (usage < 80) return 'status-indicator status-warning'; if (usage < 80) return 'status-indicator status-warning';
@ -238,25 +195,19 @@ export default {
if (health >= 60) return 'health-warning'; if (health >= 60) return 'health-warning';
return 'health-critical'; return 'health-critical';
}, },
getstatistic() {
this.loading = true
statistic().then(response => {
this.alerts = response.rows
this.loading = false
}
)
},
getbyEquType() { getbyEquType() {
this.loading = true this.loading = true
byEquType().then(response => { byEquType().then(response => {
this.loading = false this.loading = false
this.byEquTypeData = response.data
} }
) )
}, },
getlistMonitor() { getlistMonitor() {
this.loading = true this.loading = true
listMonitor().then(response => { listMonitor({pageSize: 100}).then(response => {
this.loading = false this.loading = false
this.deviceStatus = response.rows
} }
) )
}, },
@ -269,12 +220,10 @@ export default {
) )
}, },
async loadMore() { async loadMore() {
console.log("%c 🎧: loadMore -> this.isLoading || this.noMore ", "font-size:16px;background-color:#64b738;color:white;", this.isLoading , this.noMore)
if (this.isLoading || this.noMore) return; if (this.isLoading || this.noMore) return;
this.isLoading = true; this.isLoading = true;
try { try {
const res = await statistic({page:this.page}); // API const res = await statistic({page:this.page,status:'UNHANDLED'}); // API
if (res.rows.length < 10) { // 10 if (res.rows.length < 10) { // 10
this.noMore = true; this.noMore = true;
} else { } else {
@ -286,10 +235,9 @@ export default {
} finally { } finally {
this.isLoading = false; this.isLoading = false;
} }
}, }
}, },
created() { created() {
// this.getstatistic()
this.getbyEquType() this.getbyEquType()
this.getlistMonitor() this.getlistMonitor()
this.getalertMessageTimes() this.getalertMessageTimes()
@ -430,6 +378,7 @@ export default {
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
max-height: 255px; max-height: 255px;
padding-left: 0;
} }
.device-item { .device-item {

Loading…
Cancel
Save