Commit ff284b93 authored by huangcb's avatar huangcb

Merge branch 'master' into huangcb

parents 82a5b848 6313111e
......@@ -47,3 +47,20 @@ export function deleteModel(data) {
})
}
// 保存告警规则
export function saveAlarmRule(data) {
return request({
url: `${baseURL}/iot/dataModel/alarmRule/save`,
method: 'post',
data
})
}
// 获取告警规则列表
export function listAlarmRule(data) {
return request({
url: `${baseURL}/iot/dataModel/alarmRule/list`,
method: 'post',
data
})
}
......@@ -36,3 +36,12 @@ export function getModelInstanceChart(data) {
data
})
}
// 根据设备类型ID获取所有设备实例
export function getAllInstanceByDeviceTypeId(data) {
return request({
url: `${baseURL}/iot/deviceModel/instance/getInstanceByDeviceTypeId`,
method: 'post',
data
})
}
......@@ -13,7 +13,7 @@
prop="name"
>
<el-input v-model="searchForm.name" clearable placeholder="模型名称">
<el-button slot="append" icon="el-icon-search" @click="listModel(1)"></el-button>
<el-button slot="append" icon="el-icon-search" @click="listModel(1)" />
</el-input>
</el-form-item>
</el-form>
......@@ -44,6 +44,15 @@
prop="description"
label="描述"
/>
<el-table-column
label="操作"
width="140px"
align="center"
>
<template slot-scope="props">
<el-button type="text" @click="showRulesView(props.row)">告警规则</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
......@@ -87,18 +96,34 @@
@delete="onDelete()"
/>
</esv-dialog>
<esv-dialog
title="告警规则"
:visible.sync="rulesDialogVisible"
width="60%"
top="0"
>
<Rules
v-if="rulesDialogVisible"
:id="currentRowId"
:add="add"
@cancel="rulesDialogVisible = false"
@confirm="onRulesConfirm"
/>
</esv-dialog>
</div>
</template>
<script>
import Details from '@/views/data-management/model-management/detail'
import AddOrUpdate from '@/views/data-management/model-management/AddOrUpdate'
import Rules from '@/views/data-management/model-management/rules'
import { listModel } from '@/api/data-management/model-management'
export default {
name: 'ObjectModel',
components: {
Details,
AddOrUpdate
AddOrUpdate,
Rules
},
props: {},
data() {
......@@ -109,6 +134,7 @@ export default {
add: true,
dialogVisible: false,
detailDialogVisible: false,
rulesDialogVisible: false,
tableData: [
],
addForm: {
......@@ -182,9 +208,17 @@ export default {
this.dialogVisible = false
this.listModel(this.pageForm.pageNum)
},
onRulesConfirm() {
this.rulesDialogVisible = false
},
onDelete() {
this.detailDialogVisible = false
this.listModel(this.pageForm.pageNum)
},
showRulesView(row) {
this.rulesDialogVisible = true
this.currentRowId = row.id
this.add = false
}
}
}
......
<template>
<div>
<div>
<el-card>
<div slot="header" class="clearfix">
<span>规则列表</span>
<el-button style="float: right; margin-left: 10px" type="primary" @click="addRow">添加</el-button>
</div>
<el-form
ref="rulesForm"
:model="rulesForm"
class="table-form"
>
<el-table
:data="rulesForm.alarmRuleItemList"
style="width: 100%; height: 260px;"
border
>
<el-table-column
type="index"
label="序号"
width="50px"
align="center"
/>
<el-table-column
prop="propertyId"
label="数据属性"
width="155"
>
<template slot-scope="props">
<el-form-item
v-if="props.row.edit"
:prop="`alarmRuleItemList.${props.$index}.propertyId`"
label=""
style="margin-bottom: 0px"
>
<el-select v-model="props.row.propertyId">
<el-option
v-for="(item, index) in modelForm.propertyList"
:key="index"
:label="item.propertyName"
:value="item.id"
/>
</el-select>
</el-form-item>
<div v-else>{{ propertyCodeFormat(props.row.propertyId) }}</div>
</template>
</el-table-column>
<el-table-column
prop="ruleExpression"
label="判定规则"
width="155"
>
<template slot-scope="props">
<el-form-item
v-if="props.row.edit"
:prop="`alarmRuleItemList.${props.$index}.ruleExpression`"
label=""
style="margin-bottom: 0px"
>
<el-select v-model="props.row.ruleExpression">
<el-option
v-for="(item, index) in dictionary.expression"
:key="index"
:label="item.name"
:value="item.code"
/>
</el-select>
</el-form-item>
<div v-else>{{ $_dictionaryFormat(null, null, props.row.ruleExpression, null, 'expression') }}</div>
</template>
</el-table-column>
<el-table-column
prop="threshold"
label="判定值"
>
<template slot-scope="props">
<el-form-item
v-if="props.row.edit"
:prop="`alarmRuleItemList.${props.$index}.threshold`"
label=""
style="margin-bottom: 0px"
>
<el-input v-model="props.row.threshold" />
</el-form-item>
<div v-else>{{ props.row.threshold }}</div>
</template>
</el-table-column>
<el-table-column
prop="alarmLevel"
label="告警等级"
width="155"
>
<template slot-scope="props">
<el-form-item
v-if="props.row.edit"
:prop="`alarmRuleItemList.${props.$index}.alarmLevel`"
label=""
style="margin-bottom: 0px"
>
<el-select v-model="props.row.alarmLevel">
<el-option
v-for="(item, index) in dictionary.alarm_level"
:key="index"
:label="item.name"
:value="item.code"
/>
</el-select>
</el-form-item>
<div v-else>{{ $_dictionaryFormat(null, null, props.row.alarmLevel, null, 'alarm_level') }}</div>
</template>
</el-table-column>
<el-table-column
label="操作"
width="140px"
align="center"
>
<template slot-scope="props">
<el-button v-if="!props.row.edit" type="text" style="margin-right: 20px" @click="editItem(props.row)">编辑</el-button>
<el-button v-if="props.row.edit" type="text" style="margin-right: 20px" @click="finishItem(props.row)">完成</el-button>
<el-popconfirm
title="确定要删除此条记录吗?"
@onConfirm="deleteItem(props.$index)"
>
<el-button slot="reference" type="text">删除</el-button>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</el-form>
</el-card>
</div>
<div class="el-dialog__footer" style="margin-top: 20px">
<el-button @click="cancel">取消</el-button>
<el-button type="primary" @click="confirm">提交</el-button>
</div>
</div>
</template>
<script>
import dictionary from '@/utils/dictionary'
import { getModelDetail, saveAlarmRule, listAlarmRule } from '@/api/data-management/model-management'
export default {
name: 'Rules',
mixins: [dictionary],
props: {
add: {
type: Boolean,
default: true
},
id: {
type: [String, Number],
default: null
}
},
data() {
return {
rulesForm: {
modelId: null,
alarmRuleItemList: []
},
modelForm: {
name: null,
description: null,
hasInstance: false,
instanceCount: null,
propertyList: []
}
}
},
computed: {
},
created() {
if (!this.add) {
this.getModelDetail()
this.listAlarmRule()
}
},
methods: {
getModelDetail() {
getModelDetail({ id: this.id })
.then(res => {
this.rulesForm.modelId = this.id
this.modelForm = {
...res.data
}
this.modelForm.propertyList = res.data.propertyList.map(v => {
return {
propertyCode: v.propertyCode,
propertyName: v.propertyName,
propertyType: v.propertyType,
propertyDefaultValue: v.propertyDefaultValue,
propertyUnit: v.propertyUnit,
id: v.id,
edit: false
}
})
})
.catch(err => {
console.error(err.message)
this.$message.error('查询遇到问题')
})
},
listAlarmRule() {
listAlarmRule({ modelId: this.id })
.then(res => {
this.rulesForm.alarmRuleItemList = res.data.map(v => {
return {
propertyId: v.propertyId,
ruleExpression: v.ruleExpression,
threshold: v.threshold,
alarmLevel: v.alarmLevel,
edit: false
}
})
})
.catch(err => {
console.error(err.message)
this.$message.error(err.message)
})
},
cancel() {
this.$emit('cancel')
},
addRow() {
this.rulesForm.alarmRuleItemList.push({
propertyId: null,
ruleExpression: null,
threshold: null,
alarmLevel: null,
edit: true
})
if (this.rulesForm.alarmRuleItemList.length > 1) {
this.rulesForm.alarmRuleItemList[this.rulesForm.alarmRuleItemList.length - 2].edit = false
}
},
validate() {
const p = [
this.$refs.rulesForm.validate()
]
return Promise.all(p)
},
confirm() {
this.validate()
.then(_ => {
this.saveAlarmRule()
})
.catch(_ => {})
},
editItem(row) {
row.edit = true
},
finishItem(row) {
row.edit = false
},
deleteItem(index) {
this.rulesForm.alarmRuleItemList.splice(index)
},
propertyCodeFormat(propertyId) {
const property = this.modelForm.propertyList.find(v => v.id === propertyId)
return property ? property.propertyName : null
},
saveAlarmRule() {
const params = {
modelId: this.rulesForm.modelId
}
params.alarmRuleItemList = this.rulesForm.alarmRuleItemList.map(v => {
return {
propertyId: v.propertyId,
ruleExpression: v.ruleExpression,
threshold: v.threshold,
alarmLevel: v.alarmLevel
}
})
saveAlarmRule(params)
.then(_ => this.$message.success('保存成功'))
.then(_ => {
this.$emit('confirm')
})
.catch(err => {
console.error(err.message)
this.$message.error(err.message)
})
}
}
}
</script>
<style scoped>
.clearfix {
line-height: 36px;
}
</style>
......@@ -4,9 +4,13 @@
<el-col :xs="8" :sm="8" :md="6" :lg="4">
<div class="left">
<div class="search">
<el-select v-model="eModel" style="width: 100%">
<el-select
v-model="deviceType"
style="width: 100%"
@change="onDeviceTypeChange"
>
<el-option
v-for="item in eModelList"
v-for="item in deviceTypeList"
:key="item.value"
:label="item.label"
:value="item.value"
......@@ -17,42 +21,36 @@
<div class="custom-menu">
<el-menu
ref="customMenu"
default-active="1"
@select="onInstanceSelect"
>
<el-menu-item
v-for="(model, index) in eInstanceList"
:key="'model' + index"
:index="model.id.toString()"
>{{ model.name }}</el-menu-item>
v-for="(instance, index) in deviceInstanceList"
:id="'instance' + instance.id"
:key="'instance' + index"
:index="instance.id.toString()"
>{{ instance.name }}</el-menu-item>
</el-menu>
</div>
</div>
</el-col>
<el-col :xs="16" :sm="16" :md="18" :lg="20">
<el-form
:ref="'form'+activeModel"
ref="form"
:model="chartField"
inline
label-width="100px"
style="margin-top: 20px"
:rules="rules"
>
<div>
<el-form-item label="选择实例:" prop="instanceId">
<el-radio-group v-model="chartField.instanceId">
<el-radio
v-for="(ins, index) in instanceList"
:key="300 + index"
:label="ins.id"
>{{ ins.instanceName }}</el-radio>
</el-radio-group>
</el-form-item>
</div>
<div>
<el-form-item label="Y轴:" prop="yFields">
<el-checkbox-group v-model="chartField.yFields">
<div v-if="dataModelList.length">
<el-form-item
v-for="(dataModel, index) in dataModelList"
:key="index + 300"
:label='dataModel.name + ":"'
prop="yFields"
>
<el-checkbox-group v-model="chartField.yFields[index]">
<el-checkbox
v-for="(prop, i) in propertyList"
v-for="(prop, i) in dataModel.propertyList"
:key="200+i"
:label="prop.propertyCode"
>{{ prop.propertyName }}</el-checkbox>
......@@ -81,9 +79,13 @@
</el-form-item>
</div>
</el-form>
<el-row :gutter="20">
<el-row
v-for="(chartGroup, index) in chartList"
:key="index + 1000"
:gutter="20"
>
<el-col
v-for="(chart) in chartList"
v-for="(chart) in chartGroup"
:key="chart.id"
:span="12"
style="height: 400px"
......@@ -91,7 +93,7 @@
<e-line
:id="'line-' + chart.propertyCode"
:title="chart.propertyName"
:line-data="setChartData(chart.propertyCode)"
:line-data="setChartData(chart.propertyCode, index)"
:description="chart.propertyUnit"
></e-line>
</el-col>
......@@ -103,7 +105,10 @@
<script>
import ELine from '@/components/Charts/ELine'
import { getAllModel, getModelDetail, getModelInstanceList, getModelInstanceChart } from '@/api/data-visible/dashboard'
import { getModelInstanceChart } from '@/api/data-visible/dashboard'
import { getAllDeviceModel } from '@/api/equipment-management/equipment-instance'
import { getAllInstanceByDeviceTypeId } from '@/api/data-visible/dashboard'
import { getDataModelByDeviceTypeId } from '@/api/equipment-management/equipment-model'
export default {
name: 'Dashboard',
......@@ -113,46 +118,21 @@ export default {
data() {
return {
chartField: {
instanceId: null,
yFields: [],
refresh: 1
},
activeModel: null,
dataModelList: [],
deviceInstance: null,
modelList: [],
objectId: '1',
defaultActive: null,
timer: 0,
count: 0,
instanceList: [],
propertyList: [],
eModel: 1,
eModelList: [
{
value: 1,
label: '设备模型一'
},
{
value: 2,
label: '设备模型二'
}
],
eInstanceList: [
{
id: 1,
name: '设备实例一'
},
{
id: 2,
name: '设备实例二'
},
{
id: 3,
name: '设备实例三'
},
{
id: 4,
name: '设备实例四'
}
],
deviceType: null,
deviceTypeList: [],
deviceInstanceList: [],
chartData: [],
chartList: [],
rules: {
......@@ -166,44 +146,80 @@ export default {
}
},
created() {
getAllModel()
// 初始化设备类型
getAllDeviceModel()
.then(res => {
this.modelList = res.data
if (this.modelList.length > 0) {
this.activeModel = this.modelList[0].id.toString()
this.getDetail(parseInt(this.activeModel))
this.deviceTypeList = res.data.map(v => {
return {
value: v.id,
label: v.name
}
})
.catch(err => console.error(err))
if (this.deviceTypeList.length) {
this.deviceType = this.deviceTypeList[0].value
// 获取该设备类型下的设备实例
this.getAllInstanceByDeviceTypeId(this.deviceType)
// 根据设备类型 ID 获取关联数据模型
this.getDataModelByDeviceTypeId(this.deviceType)
}
})
.catch(_ => {})
},
beforeDestroy() {
clearInterval(this.timer)
},
methods: {
onTabClick() {
onDeviceTypeChange(val) {
this.dataModelList = []
this.chartField = {
instanceId: null,
yFields: [],
refresh: 1
}
this.getDetail(parseInt(this.activeModel))
this.chartList = []
this.chartData = []
clearInterval(this.timer)
this.getDataModelByDeviceTypeId(val)
this.getAllInstanceByDeviceTypeId(val)
},
onInstanceSelect(index) {
const id = parseInt(index)
const instance = this.deviceInstanceList.find(v => v.id === id)
this.deviceInstance = instance.id
},
getDataModelByDeviceTypeId(id) {
getDataModelByDeviceTypeId({ id })
.then(res => {
this.dataModelList = res.data
this.chartField.yFields = []
this.dataModelList.forEach(v => {
this.chartField.yFields.push([])
})
})
.catch(_ => {})
},
getDetail(id) {
Promise.all([getModelInstanceList({ id }), getModelDetail({ id })])
getAllInstanceByDeviceTypeId(val) {
getAllInstanceByDeviceTypeId({ deviceTypeId: val })
.then(res => {
const [res1, res2] = res
this.instanceList = res1.data
this.propertyList = res2.data.propertyList
this.deviceInstanceList = res.data
this.$nextTick()
.then(_ => {
if (this.deviceInstanceList.length) {
this.deviceInstance = this.deviceInstanceList[0].id
this.$nextTick()
.then(_ => {
document.getElementById(`instance${this.deviceInstanceList[0].id}`).click()
})
.catch(err => console.error(err))
.catch(_ => {})
}
})
})
.catch(_ => {})
},
random(m, n) {
return Math.round(Math.random() * (m - n) + n)
},
setChartData(yField) {
return this.chartData.map(v => {
setChartData(yField, index) {
return this.chartData[index].map(v => {
return {
time: v.time,
value: parseInt(v[yField])
......@@ -211,41 +227,60 @@ export default {
})
},
createCharts() {
const form = `form${this.activeModel}`
this.$refs[form].validate()
.then(_ => {
// eslint-disable-next-line no-unused-vars
let count = 0
this.chartField.yFields.forEach(v => {
if (v.length) {
count += v.length
}
})
if (count > 0) {
const params = this.dataModelList.map((v, i) => {
return {
modelId: v.id,
deviceId: this.deviceInstance,
propertyCodeList: [...this.chartField.yFields[i]]
}
})
this.chartData = []
this.chartList = []
const params = {
modelId: parseInt(this.activeModel),
instanceId: this.chartField.instanceId,
propertyCodeList: [...this.chartField.yFields]
}
getModelInstanceChart(params)
.then(res => {
this.chartData = res.data.sort((a, b) => {
this.chartData = res.data.map(v => {
const data = v.dataList.sort((a, b) => {
return (a > b) ? 1 : -1
})
return [...data]
})
this.dataModelList.forEach((dataModel, i) => {
const arr = []
this.propertyList.forEach(v => {
const index = this.chartField.yFields.findIndex(item => item === v.propertyCode)
dataModel.propertyList.forEach(v => {
const index = this.chartField.yFields[i].findIndex(item => item === v.propertyCode)
index !== -1 && arr.push({ ...v })
})
this.chartList = [...arr]
this.chartList.push(arr)
})
})
.then(_ => {
this.timer && clearInterval(this.timer)
this.timer = setInterval(async() => {
const chartData = await getModelInstanceChart(params)
this.chartData = chartData.data.sort((a, b) => {
// this.chartData = chartData.data.sort((a, b) => {
// return (a > b) ? 1 : -1
// })
this.chartData = chartData.data.map(v => {
const data = v.dataList.sort((a, b) => {
return (a > b) ? 1 : -1
})
return [...data]
})
this.count++
}, this.chartField.refresh * 1000)
})
.catch(_ => {})
})
.catch(err => console.error(err))
} else {
this.$message.warning('请至少选择 1 个属性')
}
}
}
}
......
......@@ -121,71 +121,26 @@
</el-card>
<el-dialog
:title="add ? '增加系统' : '告警详情'"
title="告警详情"
:visible.sync="dialogVisible"
width="700px"
width="800px"
>
<el-form
v-if="dialogVisible"
:model="addForm"
label-width="90px"
>
<el-form-item
label="设备类型"
>
{{ detailItem.deviceTypeName }}
</el-form-item>
<el-form-item
label="设备名称"
>
{{ detailItem.deviceName }}
</el-form-item>
<el-form-item
label="模型名称"
>
{{ detailItem.dataModelName }}
</el-form-item>
<el-form-item
label="属性代码"
>
{{ detailItem.propertyCode }}
</el-form-item>
<el-form-item
label="属性名称"
>
{{ detailItem.propertyName }}
</el-form-item>
<el-form-item
label="判定规则"
>
{{ $_dictionaryFormat(detailItem.ruleExpression, 'expression') }}
</el-form-item>
<el-form-item
label="告警等级"
>
{{ $_dictionaryFormat(detailItem.alarmLevel, 'alarm_level') }}
</el-form-item>
<el-form-item
label="阈值"
>
{{ detailItem.threshold }}
</el-form-item>
<el-form-item
label="上报值"
>
{{ detailItem.reportValue }}
</el-form-item>
<el-form-item
label="上报时间"
>
{{ $moment(detailItem.reportTime, 'YYYY-MM-DD HH:mm:ss') }}
</el-form-item>
<el-form-item
label="告警时间"
<descriptions
label-position="top"
label-width="80px"
>
{{ $moment(detailItem.alarmTime, 'YYYY-MM-DD HH:mm:ss') }}
</el-form-item>
</el-form>
<descriptions-item label="设备类型" :value="detailItem.deviceTypeName" />
<descriptions-item label="设备名称" :value="detailItem.deviceName" />
<descriptions-item label="模型名称" :value="detailItem.dataModelName" />
<descriptions-item label="属性代码" :value="detailItem.propertyCode" />
<descriptions-item label="属性名称" :value="detailItem.propertyName" />
<descriptions-item label="判定规则" :value="$_dictionaryFormat(detailItem.ruleExpression, 'expression')" />
<descriptions-item label="告警等级" :value="$_dictionaryFormat(detailItem.alarmLevel, 'alarm_level')" />
<descriptions-item label="阈值" :value="detailItem.threshold" />
<descriptions-item label="上报值" :value="detailItem.reportValue" />
<descriptions-item label="上报时间" :value="$moment(detailItem.reportTime, 'YYYY-MM-DD HH:mm:ss')" />
<descriptions-item label="告警时间" :value="$moment(detailItem.alarmTime, 'YYYY-MM-DD HH:mm:ss')" />
</descriptions>
<span slot="footer" class="dialog-footer">
<!-- <el-button @click="dialogVisible = false">取 消</el-button>-->
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
......@@ -212,7 +167,19 @@ export default {
add: true,
dialogVisible: false,
tableData: [],
detailItem: null,
detailItem: {
deviceTypeName: null,
deviceName: null,
dataModelName: null,
propertyCode: null,
propertyName: null,
ruleExpression: null,
alarmLevel: null,
threshold: null,
reportValue: null,
reportTime: null,
alarmTime: null
},
pageForm: {
pageSize: 10,
pageNum: 1,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment