fix:修复告警配置处文件缺失

master
zhangliang 7 months ago
parent 41fec38db5
commit 27c8c5fa25

@ -0,0 +1,112 @@
<template>
<j-modal
:maskClosable="false"
width="45vw"
title="编辑"
@cancel="close"
@ok="save"
visible
cancelText="取消"
okText="确定"
>
<j-form layout="vertical" :model="inputData" ref="formRef">
<j-form-item label="状态">
<j-switch
checked-children="启用"
un-checked-children="启用"
v-model:checked="inputData.status"
></j-switch>
</j-form-item>
<j-form-item
v-if="inputData.status"
label="kafka地址"
name="address"
:rules="[
{
required: true,
message: '请输入topic',
},
{
max: 64,
message: '最多输入64个字符',
},
]"
>
<j-input
v-model:value="inputData.address"
placeholder="请输入kafka地址"
></j-input>
</j-form-item>
<j-form-item
v-if="inputData.status"
label="topic"
name="topic"
:rules="[
{
required: true,
message: '请输入topic',
},
{
max: 64,
message: '最多输入64个字符',
},
]"
>
<j-input v-model:value="inputData.topic"></j-input>
</j-form-item>
</j-form>
</j-modal>
</template>
<script lang="ts" setup>
import { saveOutputData } from '@/api/rule-engine/config';
import { onlyMessage } from '@/utils/comm';
import { Form } from 'jetlinks-ui-components';
const useForm = Form.useForm;
const formRef = ref();
const Myprops = defineProps({
data: {
default: '',
},
});
let inputData = reactive({
status: false,
address: '',
topic: '',
});
watchEffect(() => {
inputData.status =
Myprops.data?.data?.state?.value === 'enabled' ? true : false;
inputData.address = Myprops.data?.data?.config?.config?.address;
inputData.topic = Myprops.data?.data?.config?.config?.topic;
});
const close = () => {
emit('closeModel');
};
const save = () => {
formRef.value.validateFields().then(() => {
saveOutputData({
config: {
sourceType: 'kafka',
config: {
...inputData,
state: inputData?.status ? 'enabled' : 'disable',
},
},
state: inputData?.status ? 'enabled' : 'disable',
id: Myprops?.data?.data?.id,
sourceType: 'kafka',
exchangeType: 'consume',
}).then((res) => {
if (res.status === 200) {
onlyMessage('操作成功');
emit('saveSuc');
}
});
});
};
const emit = defineEmits(['closeModel', 'saveSuc']);
</script>
<style lang="less" scoped>
</style>

@ -0,0 +1,112 @@
<template>
<j-modal
:maskClosable="false"
width="45vw"
title="编辑"
@cancel="close"
@ok="save"
visible
cancelText="取消"
okText="确定"
>
<j-form layout="vertical" :model="outputData" ref="formRef">
<j-form-item label="状态">
<j-switch
checked-children="启用"
un-checked-children="启用"
v-model:checked="outputData.status"
></j-switch>
</j-form-item>
<j-form-item
v-if="outputData.status"
label="kafka地址"
name="address"
:rules="[
{
required: true,
message: '请输入kafka地址',
},
{
max: 64,
message: '最多输入64个字符',
},
]"
>
<j-input
v-model:value="outputData.address"
placeholder="请输入kafka地址"
></j-input>
</j-form-item>
<j-form-item
v-if="outputData.status"
label="topic"
name="topic"
:rules="[
{
required: true,
message: '请输入topic',
},
{
max: 64,
message: '最多输入64个字符',
},
]"
>
<j-input v-model:value="outputData.topic"></j-input>
</j-form-item>
</j-form>
</j-modal>
</template>
<script lang="ts" setup>
import { saveOutputData } from '@/api/rule-engine/config';
import { onlyMessage } from '@/utils/comm';
import { Form } from 'jetlinks-ui-components';
const formRef = ref();
const useForm = Form.useForm;
const Myprops = defineProps({
data: {
default: '',
},
});
let outputData = reactive({
status: false,
address: '',
topic: '',
});
watchEffect(() => {
outputData.status =
Myprops.data?.data?.state?.value === 'enabled' ? true : false;
outputData.address = Myprops.data?.data?.config?.config?.address;
outputData.topic = Myprops.data?.data?.config?.config?.topic;
});
const close = () => {
emit('closeModel');
};
const save = () => {
formRef.value.validateFields().then(() => {
saveOutputData({
config: {
sourceType: 'kafka',
config: {
...outputData,
state: outputData?.status ? 'enabled' : 'disable',
},
},
state: outputData?.status ? 'enabled' : 'disable',
id: Myprops?.data?.data?.id,
sourceType: 'kafka',
exchangeType: 'producer',
}).then((res) => {
if (res.status === 200) {
onlyMessage('操作成功');
emit('saveSuc');
}
});
});
};
const emit = defineEmits(['closeModel', 'saveSuc']);
</script>
<style lang="less" scoped>
</style>

@ -0,0 +1,537 @@
<template>
<div>
<j-row :gutter="24">
<j-col :span="14">
<div class="alarmFlow-left">
<j-card
:head-style="{ borderBottom: 'none', height: '30px' }"
:bordered="false"
>
<template #title>
<div class="alarmTitle">
<span>告警数据输出</span>
<j-tooltip
title="将告警数据输出到其他第三方系统"
>
<AIcon
type="QuestionCircleOutlined"
style="
margin-left: 6px;
line-height: 35px;
"
/>
</j-tooltip>
<PermissionButton
type="link"
@click="showOutput"
hasPermission="device/Instance:update"
>
<template #icon
><AIcon type="EditOutlined"
/></template>
</PermissionButton>
</div>
</template>
<j-descriptions
bordered
:labelStyle="{ width: 112 + 'px' }"
:contentStyle="{ minWidth: 100 + 'px' }"
:column="2"
>
<j-descriptions-item
label="kafka地址"
:content-style="{ minWidth: '200px' }"
><j-badge
:status="
output?.running ? 'success' : 'error'
"
:text="
output?.data?.config?.config?.address ||
''
"
></j-badge
></j-descriptions-item>
<j-descriptions-item label="topic">{{
output?.data?.config?.config?.topic || ''
}}</j-descriptions-item>
<j-descriptions-item label="状态" :span="2"
><j-badge
:status="
output?.data?.state?.value === 'enabled'
? 'success'
: 'error'
"
:text="output?.data?.state?.text || ''"
></j-badge
></j-descriptions-item>
</j-descriptions>
</j-card>
<j-card
:head-style="{ borderBottom: 'none', height: '30px' }"
:bordered="false"
>
<template #title>
<div class="alarmTitle">
<span>告警处理结果输入</span>
<j-tooltip title="接收第三方系统处理的告警结果">
<AIcon
type="QuestionCircleOutlined"
style="
margin-left: 6px;
line-height: 35px;
"
/>
</j-tooltip>
<PermissionButton
type="link"
@click="showInput"
hasPermission="device/Instance:update"
>
<template #icon
><AIcon type="EditOutlined" /></template
></PermissionButton>
</div>
</template>
<j-descriptions
bordered
:labelStyle="{ width: 112 + 'px' }"
:contentStyle="{ minWidth: 150 + 'px' }"
:column="2"
>
<j-descriptions-item label="kafka地址"
><j-badge
:status="
input?.running ? 'success' : 'error'
"
:text="
input?.data?.config?.config?.address ||
''
"
></j-badge
></j-descriptions-item>
<j-descriptions-item label="topic">{{
input?.data?.config?.config?.topic || ''
}}</j-descriptions-item>
<j-descriptions-item label="状态" :span="2"
><j-badge
:status="
input?.data?.state?.value === 'enabled'
? 'success'
: 'error'
"
:text="input?.data?.state?.text || ''"
></j-badge
></j-descriptions-item>
</j-descriptions>
</j-card>
</div>
</j-col>
<j-col :span="10">
<div class="alarmFlow-right">
<div class="doc">
<h1>功能图示</h1>
<div class="image">
<j-image
width="100%"
:src="getImage('/alarm/io.png')"
></j-image>
</div>
<h1>功能说明</h1>
<div>
1平台支持将告警数据输出到kafka第三方系统可订阅kafka中的告警数据进行业务处理
</div>
<h2>推送参数</h2>
<div>
<j-table
:dataSource="outputData"
:pagination="false"
:columns="outputColumns"
></j-table>
</div>
<h2>示例</h2>
<div v-html="markdownOutputText" class="code"></div>
<div>
2平台支持订阅kafka中告警处理数据并更新告警记录状态
</div>
<h2>订阅参数</h2>
<div>
<j-table
:dataSource="subData"
:pagination="false"
:columns="subColumns"
></j-table>
</div>
<h2>示例</h2>
<div class="code" v-html="markdownSubText"></div>
</div>
</div>
</j-col>
</j-row>
<InputSave
:data="input"
v-if="inputVisible"
@closeModel="closeInput"
@saveSuc="saveInput"
/>
<OutputSave
:data="output"
v-if="outputVisible"
@closeModel="closeOutput"
@saveSuc="saveOutput"
/>
</div>
</template>
<script lang="ts" setup>
import InputSave from './Save/input.vue';
import OutputSave from './Save/output.vue';
import { getDataExchange } from '@/api/rule-engine/config';
import { getImage } from '@/utils/comm';
import { marked } from 'marked';
let input = ref<any>();
let output = ref<any>();
const outputData = [
{
key: 'alarmConfigName',
name: '告警配置名称',
type: 'string',
desc: '推送的告警配置名称',
example: '烟感告警',
},
{
key: 'alarmConfigId',
name: '告警配置ID',
type: 'string',
desc: '推送的告警配置ID',
example: '1605111722418597888',
},
{
key: 'Id',
name: '告警数据ID',
type: 'string',
desc: '告警唯一性标识',
example: '1515992841393119232',
},
{
key: 'alarmRecordId',
name: '告警记录ID',
type: 'string',
desc: '告警记录的唯一标识可根据此ID处理告警',
example: 'ba33a59ca5ebe3dccfcd75fd0575be4e',
},
{
key: 'targetType',
name: '告警目标类型',
type: 'string',
desc: '告警所属的业务类型,具体有产品、设备、部门、其他',
example: '产品',
},
{
key: 'targetId',
name: '告警目标ID',
type: 'string',
desc: '告警目标唯一性标识',
example: '1583300346713661440',
},
{
key: 'targetName',
name: '告警目标名称',
type: 'string',
desc: '告警目标实例名称',
example: '海康烟感',
},
{
key: 'alarmTime',
name: '告警时间',
type: 'long',
desc: '告警触发时间',
example: '1651233650840',
},
{
key: 'sourceType',
name: '告警源类型',
type: 'string',
desc: '触发告警的源类型。当前只有device',
example: 'device',
},
{
key: 'sourceId',
name: '告警源ID',
type: 'string',
desc: '触发告警的源Id。如设备Id',
example: '1605138218826821632',
},
{
key: 'sourceName',
name: '告警源名称',
type: 'string',
desc: '触发告警的源名称。如设备名称',
example: '1楼烟感S01',
},
{
key: 'level',
name: '告警级别',
type: 'int',
desc: '告警严重程度指标',
example: 1,
},
{
key: 'description',
name: '告警说明',
type: 'string',
desc: '告警规则说明',
example: '1楼烟感统一告警规则设置',
},
];
const subData = [
{
key: 'alarmRecordId',
name: '告警记录ID',
type: 'string',
require: '是',
desc: '告警记录的唯一标识可根据此ID处理告警',
example: 'ba33a59ca5ebe3dccfcd75fd0575be4e',
},
{
key: 'alarmConfigId',
name: '告警配置ID',
type: 'string',
require: '是',
desc: '推送的告警配置ID',
example: '1605111722418597888',
},
{
key: 'alarmTime',
name: '告警时间',
type: 'long',
require: '是',
desc: '告警触发时间',
example: '1651233650840',
},
{
key: 'handleTime',
name: '处理时间',
type: 'long',
require: '是',
desc: '告警处理时间,不填是默认为消息处理时间',
example: '1651233650840',
},
{
key: 'describe',
name: '处理说明',
type: 'string',
require: '是',
desc: '告警处理内容详细描述说明',
example: '已联系第三方人员进行告警处理,现告警已恢复',
},
{
key: 'type',
name: '处理类型',
type: 'enum',
require: '是',
desc: '支持system、user',
example: 'user',
},
{
key: 'state',
name: '处理后的状态',
type: 'enum',
require: '是',
desc: 'warning、normal',
example: 'normal',
},
];
const outputColumns = [
{
title: '名称',
dataIndex: 'name',
key: 'name',
ellipsis: true,
},
{
title: '标识',
dataIndex: 'key',
key: 'key',
ellipsis: true,
},
{
title: '类型',
dataIndex: 'type',
key: 'type',
ellipsis: true,
},
{
title: '说明',
dataIndex: 'desc',
key: 'desc',
width: 100,
ellipsis: true,
},
{
title: '示例值',
dataIndex: 'example',
key: 'example',
width: 100,
ellipsis: true,
},
];
const subColumns = [...outputColumns];
subColumns.splice(3, 0, {
title: '必填',
dataIndex: 'require',
key: 'require',
ellipsis: true,
});
const subText = `
~~~json
{
"alarmRecordId": "ba33a59ca5ebe3dccfcd75fd0575be4e",
"alarmConfigId": "1605111722418597888",
"alarmTime": "1651233650840",
"handleTime": "1651233650841",
"describe": "已联系第三方人员进行告警处理,现告警已恢复",
"type": "user",
"state": "normal"
}
~~~
`;
const outputText = `
~~~json
{
"alarmConfigId": "1605111722418597888",
"id": "1515992841393119232",
"alarmConfigId": "1586989804257853441",
"alarmConfigName": "烟感告警",
"alarmRecordId": "ba33a59ca5ebe3dccfcd75fd0575be4e",
"level": "3",
"description": "设备温度过高",
"alarmTime": "1667202964007",
"sourceType": "device",
"sourceId": "1605138218826821632",
"sourceName": "1楼烟感S01",
"targetType": "device",
"targetName": "温度探测设备",
"targetId": "1583300346713661440"
}
~~~
`;
const render = new marked.Renderer();
const markdownSubText = shallowRef(marked(subText));
const markdownOutputText = shallowRef(marked(outputText));
let inputVisible = ref(false);
let outputVisible = ref(false);
marked.setOptions({
renderer: render,
gfm: true,
pedantic: false,
});
const handleOutputSearch = () => {
getDataExchange('producer').then((res) => {
if (res.status === 200) {
output.value = res.result;
}
});
};
const handleInputSearch = () => {
getDataExchange('consume').then((res) => {
if (res.status === 200) {
input.value = res.result;
}
});
};
handleInputSearch();
handleOutputSearch();
const showInput = () => {
inputVisible.value = true;
};
const closeInput = () => {
inputVisible.value = false;
};
const saveInput = () => {
inputVisible.value = false;
handleInputSearch();
};
const showOutput = () => {
outputVisible.value = true;
};
const closeOutput = () => {
outputVisible.value = false;
};
const saveOutput = () => {
outputVisible.value = false;
handleOutputSearch();
};
</script>
<style lang="less" scoped>
.alarmTitle {
display: flex;
position: relative;
padding-left: 10px;
color: rgba(0, 0, 0, 0.8);
font-weight: 600;
line-height: 1;
margin-bottom: 16px;
line-height: 30px;
}
.alarmTitle::before {
position: absolute;
top: 0;
left: 0;
width: 4px;
height: 100%;
background-color: #1d39c4;
border-radius: 0 3px 3px 0;
content: ' ';
}
.alarmFlow-left,
.alarmFlow-right {
height: 780px;
background-color: white;
}
.alarmFlow-right {
margin-left: 20px;
padding-bottom: 24px;
}
.doc {
height: 100%;
padding: 24px;
overflow-y: auto;
color: rgba(#000, 0.8);
font-size: 14px;
background-color: #fff;
.url {
padding: 8px 16px;
color: #2f54eb;
background-color: rgba(#a7bdf7, 0.2);
}
h1 {
margin: 16px 0;
color: rgba(#000, 0.85);
font-weight: bold;
font-size: 14px;
&:first-child {
margin-top: 0;
}
}
h2 {
margin: 6px 10px;
color: rgba(0, 0, 0, 0.8);
font-weight: 400;
font-size: 14px;
}
.image {
margin: 16px 0;
}
.code {
padding: 16px;
background-color: #fafafa;
}
}
</style>
Loading…
Cancel
Save