feat: 告警中心告警配置40%
This commit is contained in:
parent
1003130a4c
commit
6a275ee983
|
@ -18,4 +18,20 @@ export const remove = (id:string) => server.remove(`/alarm/config/${id}`);
|
|||
/**
|
||||
* 手动触发告警
|
||||
*/
|
||||
export const _execute = (data:any) => server.post('/scene/batch/_execute',data)
|
||||
export const _execute = (data:any) => server.post('/scene/batch/_execute',data);
|
||||
/**
|
||||
* 下拉框场景数据
|
||||
*/
|
||||
export const getScene = (params:Record<string,any>) => server.get('/scene/_query/no-paging?paging=false',params);
|
||||
/**
|
||||
* 获取配置类型
|
||||
*/
|
||||
export const getTargetTypes = () => server.get('/alarm/config/target-type/supports');
|
||||
/**
|
||||
* 保存基本设置
|
||||
*/
|
||||
export const save = (data:any) =>server.post('/alarm/config',data);
|
||||
/**
|
||||
* 获取基础设置数据
|
||||
*/
|
||||
export const detail = (id:string) => server.get(`/alarm/config/${id}`);
|
|
@ -5,4 +5,6 @@ export const modify = (id: string, data: any) => server.put(`/scene/${id}`, data
|
|||
|
||||
export const save = (data: any) => server.post(`/scene`, data)
|
||||
|
||||
export const detail = (id: string) => server.get(`/scene/${id}`)
|
||||
export const detail = (id: string) => server.get(`/scene/${id}`)
|
||||
|
||||
export const query = (data: any) => server.post('/scene/_query/',data);
|
|
@ -0,0 +1,203 @@
|
|||
<template>
|
||||
<div>
|
||||
<a-form layout="vertical" :rules="rule" :model="form" ref="formRef">
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="名称" name="name">
|
||||
<a-input
|
||||
placeholder="请输入名称"
|
||||
v-model:value="form.name"
|
||||
></a-input> </a-form-item
|
||||
></a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="类型" name="targetType">
|
||||
<a-select
|
||||
:options="options"
|
||||
v-model:value="form.targetType"
|
||||
:disabled="selectDisable"
|
||||
></a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-form-item label="级别" name="level">
|
||||
<a-radio-group v-model:value="form.level">
|
||||
<a-radio-button
|
||||
v-for="(item, index) in levelOption"
|
||||
:key="index"
|
||||
:value="item.value"
|
||||
>
|
||||
<div
|
||||
style="
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
font-size: 15px;
|
||||
width: 90%;
|
||||
"
|
||||
>
|
||||
<img
|
||||
:src="getImage(`/alarm/alarm${index + 1}.png`)"
|
||||
style="height: 40px"
|
||||
alt=""
|
||||
/>{{ item.label }}
|
||||
</div>
|
||||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="说明" name="description">
|
||||
<a-textarea v-model:value="form.description"></a-textarea>
|
||||
</a-form-item>
|
||||
<a-button type="primary" @click="handleSave" :loading="loading"
|
||||
>保存</a-button
|
||||
>
|
||||
</a-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getTargetTypes, save, detail } from '@/api/rule-engine/configuration';
|
||||
import { queryLevel } from '@/api/rule-engine/config';
|
||||
import { query } from '@/api/rule-engine/scene';
|
||||
import { getImage } from '@/utils/comm';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { Store } from 'jetlinks-store';
|
||||
const route = useRoute();
|
||||
const id = route.query?.id;
|
||||
let selectDisable = ref(false);
|
||||
const queryData = () => {
|
||||
if (id) {
|
||||
detail(id).then((res) => {
|
||||
if (res.status === 200) {
|
||||
form.level = res?.result?.level;
|
||||
form.name = res?.result?.name;
|
||||
form.targetType = res?.result?.targetType;
|
||||
form.description = res?.result?.description;
|
||||
Store.set('configuration-data', res.result);
|
||||
query({
|
||||
terms: [
|
||||
{
|
||||
terms: [
|
||||
{
|
||||
column: 'id',
|
||||
termType: 'alarm-bind-rule',
|
||||
value: id,
|
||||
},
|
||||
],
|
||||
type: 'and',
|
||||
},
|
||||
],
|
||||
sorts: [
|
||||
{
|
||||
name: 'createTime',
|
||||
order: 'desc',
|
||||
},
|
||||
],
|
||||
}).then((resq) => {
|
||||
if (resq.status === 200) {
|
||||
selectDisable.value = !!resq.result.data?.length;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
const rule = {
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入名称',
|
||||
},
|
||||
{
|
||||
max: 64,
|
||||
message: '最多输入64个字符',
|
||||
},
|
||||
],
|
||||
targetType: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择类型',
|
||||
},
|
||||
],
|
||||
level: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择级别',
|
||||
},
|
||||
],
|
||||
description: [
|
||||
{
|
||||
max: 200,
|
||||
message: '最多可输入200个字符',
|
||||
},
|
||||
],
|
||||
};
|
||||
let form = reactive({
|
||||
level: '',
|
||||
targetType: '',
|
||||
name: '',
|
||||
description: '',
|
||||
});
|
||||
let options = ref();
|
||||
let levelOption = ref();
|
||||
let loading = ref(false);
|
||||
const formRef = ref();
|
||||
const menuStory = useMenuStore();
|
||||
const getSupports = async () => {
|
||||
let res = await getTargetTypes();
|
||||
if (res.status === 200) {
|
||||
options.value = res.result.map(
|
||||
(item: { id: string; name: string }) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
getSupports();
|
||||
const getLevel = () => {
|
||||
queryLevel().then((res) => {
|
||||
if (res.status === 200) {
|
||||
levelOption.value = res.result?.levels
|
||||
?.filter((i: any) => i?.level && i?.title)
|
||||
.map((item: { level: number; title: string }) => ({
|
||||
label: item.title,
|
||||
value: item.level,
|
||||
}));
|
||||
}
|
||||
});
|
||||
};
|
||||
getLevel();
|
||||
const handleSave = async () => {
|
||||
loading.value = true;
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(async () => {
|
||||
const res = await save(form);
|
||||
loading.value = false;
|
||||
if (res.status === 200) {
|
||||
message.success('操作成功');
|
||||
menuStory.jumpPage(
|
||||
'rule-engine/Alarm/Configuration/Save',
|
||||
{},
|
||||
{ id: res.result?.id },
|
||||
);
|
||||
if (!id) {
|
||||
Store.set('configuration-data', res.result);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
loading.value = false;
|
||||
console.log(error);
|
||||
});
|
||||
};
|
||||
queryData();
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.ant-radio-button-wrapper {
|
||||
margin: 10px 15px 0 0;
|
||||
width: 125px;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,9 @@
|
|||
<template>
|
||||
<div>123</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
</style>
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<a-card>
|
||||
<a-tabs v-model:activeKey="activeKey">
|
||||
<a-tab-pane key="1" tab="基础配置">
|
||||
<Base/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab="关联场景联动">
|
||||
<Scene></Scene>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="3" tab="告警记录"></a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-card>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import Base from './Base/index.vue';
|
||||
import Scene from './Scene/index.vue'
|
||||
const activeKey = ref('2');
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
</style>
|
|
@ -2,7 +2,7 @@
|
|||
<page-container>
|
||||
<div>
|
||||
<Search
|
||||
:columns="query.columns"
|
||||
:columns="columns"
|
||||
target="device-instance"
|
||||
@search="handleSearch"
|
||||
></Search>
|
||||
|
@ -13,6 +13,7 @@
|
|||
:defaultParams="{
|
||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||
}"
|
||||
:params="params"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<a-space>
|
||||
|
@ -41,23 +42,27 @@
|
|||
</slot>
|
||||
</template>
|
||||
<template #content>
|
||||
<h3 style="font-weight: 600">
|
||||
{{ slotProps.name }}
|
||||
</h3>
|
||||
<Ellipsis>
|
||||
<span style="font-weight: 600; font-size: 16px">
|
||||
{{ slotProps.name }}
|
||||
</span>
|
||||
</Ellipsis>
|
||||
<a-row>
|
||||
<a-col :span="12">
|
||||
<div class="content-des-title">
|
||||
关联场景联动
|
||||
</div>
|
||||
<div class="rule-desc">
|
||||
{{ (slotProps?.scene || []).map((item: any) => item?.name).join(',') || '' }}
|
||||
</div>
|
||||
<Ellipsis
|
||||
><div>
|
||||
{{ (slotProps?.scene || []).map((item: any) => item?.name).join(',') || '' }}
|
||||
</div></Ellipsis
|
||||
>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<div class="content-des-title">
|
||||
告警级别
|
||||
</div>
|
||||
<div class="rule-desc">
|
||||
<div>
|
||||
{{ (Store.get('default-level') || []).find((item: any) => item?.level === slotProps.level)?.title ||
|
||||
slotProps.level }}
|
||||
</div>
|
||||
|
@ -200,6 +205,7 @@ import {
|
|||
_disable,
|
||||
remove,
|
||||
_execute,
|
||||
getScene,
|
||||
} from '@/api/rule-engine/configuration';
|
||||
import { queryLevel } from '@/api/rule-engine/config';
|
||||
import { Store } from 'jetlinks-store';
|
||||
|
@ -207,6 +213,8 @@ import type { ActionsType } from '@/components/Table/index.vue';
|
|||
import { message } from 'ant-design-vue';
|
||||
import { getImage } from '@/utils/comm';
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
import encodeQuery from '@/utils/encodeQuery';
|
||||
import { useStorage } from '@vueuse/core';
|
||||
const params = ref<Record<string, any>>({});
|
||||
let isAdd = ref<number>(0);
|
||||
let title = ref<string>('');
|
||||
|
@ -217,35 +225,104 @@ const columns = [
|
|||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '类型',
|
||||
dataIndex: 'targetType',
|
||||
key: 'targetType',
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{
|
||||
label: '产品',
|
||||
value: 'product',
|
||||
},
|
||||
{
|
||||
label: '设备',
|
||||
value: 'device',
|
||||
},
|
||||
{
|
||||
label: '组织',
|
||||
value: 'org',
|
||||
},
|
||||
{
|
||||
label: '其他',
|
||||
value: 'other',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '告警级别',
|
||||
dataIndex: 'level',
|
||||
key: 'level',
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: async () => {
|
||||
const res = await queryLevel();
|
||||
if (res.status === 200) {
|
||||
return (res?.result?.levels || [])
|
||||
.filter((i: any) => i?.level && i?.title)
|
||||
.map((item: any) => ({
|
||||
label: item.title,
|
||||
value: item.level,
|
||||
}));
|
||||
}
|
||||
return [];
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '关联场景联动',
|
||||
dataIndex: 'sceneId',
|
||||
wdith: 250,
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: async () => {
|
||||
const res = await getScene(
|
||||
encodeQuery({
|
||||
sorts: { createTime: 'desc' },
|
||||
}),
|
||||
);
|
||||
if(res.status === 200){
|
||||
return res.result.map((item:any) => ({label:item.name, value:item.id}))
|
||||
}
|
||||
return [];
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'state',
|
||||
key: 'state',
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{
|
||||
label: '正常',
|
||||
value: 'enabled',
|
||||
},
|
||||
{
|
||||
label: '禁用',
|
||||
value: 'disabled',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '说明',
|
||||
dataIndex: 'description',
|
||||
key: 'description',
|
||||
search:{
|
||||
type:'string',
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
|
@ -261,44 +338,6 @@ const map = {
|
|||
org: '组织',
|
||||
other: '其他',
|
||||
};
|
||||
const query = {
|
||||
columns: [
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'state',
|
||||
key: 'state',
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{
|
||||
label: '正常',
|
||||
value: 'enabled',
|
||||
},
|
||||
{
|
||||
label: '禁用',
|
||||
value: 'disabled',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '说明',
|
||||
key: 'description',
|
||||
dataIndex: 'description',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
const handleSearch = (e: any) => {
|
||||
params.value = e;
|
||||
};
|
||||
|
@ -357,9 +396,7 @@ const getActions = (
|
|||
|
||||
icon: 'EditOutlined',
|
||||
onClick: () => {
|
||||
title.value = '编辑';
|
||||
isAdd.value = 2;
|
||||
nextTick(() => {});
|
||||
menuStory.jumpPage('rule-engine/Alarm/Configuration/Save',{},{id:data.id});
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -423,17 +460,12 @@ const getActions = (
|
|||
return actions.filter((i: ActionsType) => i.key !== 'view');
|
||||
return actions;
|
||||
};
|
||||
const add = () =>{
|
||||
// menuStory.jumpPage()
|
||||
}
|
||||
const add = () => {
|
||||
menuStory.jumpPage('rule-engine/Alarm/Configuration/Save');
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.content-des-title {
|
||||
font-size: 12px;
|
||||
}
|
||||
.rule-desc {
|
||||
white-space: nowrap; /*强制在同一行内显示所有文本,直到文本结束或者遭遇br标签对象才换行。*/
|
||||
overflow: hidden; /*超出部分隐藏*/
|
||||
text-overflow: ellipsis; /*隐藏部分以省略号代替*/
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,9 @@
|
|||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
</style>
|
Loading…
Reference in New Issue