feat(iot):优化 alert 的代码实现。

pull/345/head
YunaiV 2026-05-18 12:36:58 +08:00
parent 81b4690998
commit 88515705dc
5 changed files with 38 additions and 51 deletions

View File

@ -9,6 +9,7 @@ import { getSimpleUserList } from '#/api/system/user';
import { getRangePickerDefaultProps } from '#/utils'; import { getRangePickerDefaultProps } from '#/utils';
/** 新增/修改告警配置的表单 */ /** 新增/修改告警配置的表单 */
// TODO @AI两行=》1 行;
export function useFormSchema(): VbenFormSchema[] { export function useFormSchema(): VbenFormSchema[] {
return [ return [
{ {
@ -28,6 +29,7 @@ export function useFormSchema(): VbenFormSchema[] {
}, },
rules: 'required', rules: 'required',
}, },
// TODO @AIvue + ep 貌似也要改成 teatarea
{ {
fieldName: 'description', fieldName: 'description',
label: '配置描述', label: '配置描述',
@ -56,8 +58,11 @@ export function useFormSchema(): VbenFormSchema[] {
buttonStyle: 'solid', buttonStyle: 'solid',
optionType: 'button', optionType: 'button',
}, },
// TODO @AIdefaultValue 这种要枚举值哇?
defaultValue: 0,
rules: 'required', rules: 'required',
}, },
// TODO @AI可能 label 比较宽,需要拉长点。
{ {
fieldName: 'sceneRuleIds', fieldName: 'sceneRuleIds',
label: '关联场景联动规则', label: '关联场景联动规则',
@ -69,6 +74,7 @@ export function useFormSchema(): VbenFormSchema[] {
mode: 'multiple', mode: 'multiple',
placeholder: '请选择关联的场景联动规则', placeholder: '请选择关联的场景联动规则',
}, },
defaultValue: [],
rules: 'required', rules: 'required',
}, },
{ {
@ -82,6 +88,7 @@ export function useFormSchema(): VbenFormSchema[] {
mode: 'multiple', mode: 'multiple',
placeholder: '请选择接收的用户', placeholder: '请选择接收的用户',
}, },
defaultValue: [],
rules: 'required', rules: 'required',
}, },
{ {
@ -93,6 +100,7 @@ export function useFormSchema(): VbenFormSchema[] {
mode: 'multiple', mode: 'multiple',
placeholder: '请选择接收类型', placeholder: '请选择接收类型',
}, },
defaultValue: [],
rules: 'required', rules: 'required',
}, },
]; ];
@ -155,7 +163,10 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
field: 'level', field: 'level',
title: '告警级别', title: '告警级别',
minWidth: 100, minWidth: 100,
slots: { default: 'level' }, cellRender: {
name: 'CellDict',
props: { type: DICT_TYPE.IOT_ALERT_LEVEL },
},
}, },
{ {
field: 'status', field: 'status',
@ -170,7 +181,7 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
field: 'sceneRuleIds', field: 'sceneRuleIds',
title: '关联场景联动规则', title: '关联场景联动规则',
minWidth: 150, minWidth: 150,
slots: { default: 'sceneRules' }, formatter: ({ cellValue }) => `${cellValue?.length || 0}`,
}, },
{ {
field: 'receiveUserNames', field: 'receiveUserNames',

View File

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { AlertConfig } from '#/api/iot/alert/config'; import type { AlertConfigApi } from '#/api/iot/alert/config';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
import { DICT_TYPE } from '@vben/constants'; import { DICT_TYPE } from '@vben/constants';
@ -12,7 +12,7 @@ import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import { deleteAlertConfig, getAlertConfigPage } from '#/api/iot/alert/config'; import { deleteAlertConfig, getAlertConfigPage } from '#/api/iot/alert/config';
import { $t } from '#/locales'; import { $t } from '#/locales';
import AlertConfigForm from '../modules/alert-config-form.vue'; import AlertConfigForm from '../modules/form.vue';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';
defineOptions({ name: 'IoTAlertConfig' }); defineOptions({ name: 'IoTAlertConfig' });
@ -33,12 +33,12 @@ function handleCreate() {
} }
/** 编辑告警配置 */ /** 编辑告警配置 */
function handleEdit(row: AlertConfig) { function handleEdit(row: AlertConfigApi.AlertConfig) {
formModalApi.setData(row).open(); formModalApi.setData(row).open();
} }
/** 删除告警配置 */ /** 删除告警配置 */
async function handleDelete(row: AlertConfig) { async function handleDelete(row: AlertConfigApi.AlertConfig) {
const hideLoading = message.loading({ const hideLoading = message.loading({
content: $t('ui.actionMessage.deleting', [row.name]), content: $t('ui.actionMessage.deleting', [row.name]),
duration: 0, duration: 0,
@ -81,7 +81,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
refresh: true, refresh: true,
search: true, search: true,
}, },
} as VxeTableGridOptions<AlertConfig>, } as VxeTableGridOptions<AlertConfigApi.AlertConfig>,
}); });
</script> </script>
@ -102,20 +102,9 @@ const [Grid, gridApi] = useVbenVxeGrid({
]" ]"
/> />
</template> </template>
<!-- TODO @AI可以在 data 里渲染么应该 antd 里有例子的 --> <!-- TODO DONE @AI告警级别已改用 CellDict data.ts 渲染 -->
<!-- 告警级别列 --> <!-- TODO DONE @AI关联场景联动规则计数已改用 formatter data.ts 渲染 -->
<template #level="{ row }"> <!-- TODO DONE @AI接收类型是 number[] TagCellDict 只能渲染单值保留 slot -->
<Tag>
{{ getDictLabel(DICT_TYPE.IOT_ALERT_LEVEL, row.level) }}
</Tag>
</template>
<!-- TODO @AI可以在 data 里渲染么应该 antd 里有例子的 -->
<!-- 关联场景联动规则列 -->
<template #sceneRules="{ row }">
<span>{{ row.sceneRuleIds?.length || 0 }} </span>
</template>
<!-- TODO @AI可以在 data 里渲染么应该 antd 里有例子的 -->
<!-- 接收类型列 -->
<template #receiveTypes="{ row }"> <template #receiveTypes="{ row }">
<Tag <Tag
v-for="(type, index) in row.receiveTypes" v-for="(type, index) in row.receiveTypes"

View File

@ -1,7 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
// TODO @AI form.vue system user form // TODO @AIconfig/modules
// TODO @AI system user form import type { AlertConfigApi } from '#/api/iot/alert/config';
import type { AlertConfig } from '#/api/iot/alert/config';
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
@ -22,7 +21,7 @@ import { useFormSchema } from '../config/data';
defineOptions({ name: 'IoTAlertConfigForm' }); defineOptions({ name: 'IoTAlertConfigForm' });
const emit = defineEmits(['success']); const emit = defineEmits(['success']);
const formData = ref<AlertConfig>(); const formData = ref<AlertConfigApi.AlertConfig>();
const getTitle = computed(() => { const getTitle = computed(() => {
return formData.value?.id return formData.value?.id
? $t('ui.actionTitle.edit', ['告警配置']) ? $t('ui.actionTitle.edit', ['告警配置'])
@ -49,7 +48,7 @@ const [Modal, modalApi] = useVbenModal({
} }
modalApi.lock(); modalApi.lock();
// //
const data = (await formApi.getValues()) as AlertConfig; const data = (await formApi.getValues()) as AlertConfigApi.AlertConfig;
try { try {
await (formData.value?.id await (formData.value?.id
? updateAlertConfig(data) ? updateAlertConfig(data)
@ -68,16 +67,8 @@ const [Modal, modalApi] = useVbenModal({
return; return;
} }
// //
const data = modalApi.getData<AlertConfig>(); const data = modalApi.getData<AlertConfigApi.AlertConfig>();
if (!data || !data.id) { if (!data || !data.id) {
//
// TODO @AIstatus data.ts
await formApi.setValues({
status: 0,
sceneRuleIds: [],
receiveUserIds: [],
receiveTypes: [],
});
return; return;
} }
modalApi.lock(); modalApi.lock();

View File

@ -101,7 +101,10 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
field: 'configLevel', field: 'configLevel',
title: '告警级别', title: '告警级别',
minWidth: 100, minWidth: 100,
slots: { default: 'configLevel' }, cellRender: {
name: 'CellDict',
props: { type: DICT_TYPE.IOT_ALERT_LEVEL },
},
}, },
{ {
field: 'productId', field: 'productId',

View File

@ -1,7 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
// TODO @AI antd 1 modules2process
import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { AlertRecord } from '#/api/iot/alert/record'; import type { AlertRecordApi } from '#/api/iot/alert/record';
import { h, ref } from 'vue'; import { h, ref } from 'vue';
@ -10,7 +9,7 @@ import { DICT_TYPE } from '@vben/constants';
import { getDictLabel } from '@vben/hooks'; import { getDictLabel } from '@vben/hooks';
import { IconifyIcon } from '@vben/icons'; import { IconifyIcon } from '@vben/icons';
import { Button, Input, message, Modal, Popover, Tag } from 'ant-design-vue'; import { Button, Input, message, Modal, Popover } from 'ant-design-vue';
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import { getAlertRecordPage, processAlertRecord } from '#/api/iot/alert/record'; import { getAlertRecordPage, processAlertRecord } from '#/api/iot/alert/record';
@ -25,7 +24,7 @@ function handleRefresh() {
} }
/** 处理告警记录 */ /** 处理告警记录 */
function handleProcess(row: AlertRecord) { function handleProcess(row: AlertRecordApi.AlertRecord) {
const processRemark = ref(''); const processRemark = ref('');
Modal.confirm({ Modal.confirm({
title: '处理告警记录', title: '处理告警记录',
@ -60,7 +59,8 @@ function handleProcess(row: AlertRecord) {
} }
/** 查看告警记录详情 */ /** 查看告警记录详情 */
function handleView(row: AlertRecord) { // TODO @AI view vue3 + ep
function handleView(row: AlertRecordApi.AlertRecord) {
const deviceMessageText = const deviceMessageText =
row.deviceMessage && typeof row.deviceMessage === 'object' row.deviceMessage && typeof row.deviceMessage === 'object'
? JSON.stringify(row.deviceMessage, null, 2) ? JSON.stringify(row.deviceMessage, null, 2)
@ -132,7 +132,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
refresh: true, refresh: true,
search: true, search: true,
}, },
} as VxeTableGridOptions<AlertRecord>, } as VxeTableGridOptions<AlertRecordApi.AlertRecord>,
}); });
/** 把设备消息序列化成可读字符串 */ /** 把设备消息序列化成可读字符串 */
@ -149,15 +149,8 @@ function stringifyDeviceMessage(deviceMessage: any) {
<template> <template>
<Page auto-content-height> <Page auto-content-height>
<Grid table-title=""> <Grid table-title="">
<!-- 告警级别列 --> <!-- TODO DONE @AI告警级别已改用 CellDict data.ts 渲染 -->
<!-- TODO @AI可以在 data 里渲染么应该 antd 里有例子的 --> <!-- TODO DONE @AI设备消息是 Popover hover JSON 详情CellDict 只渲染单值文本保留 slot -->
<template #configLevel="{ row }">
<Tag>
{{ getDictLabel(DICT_TYPE.IOT_ALERT_LEVEL, row.configLevel) }}
</Tag>
</template>
<!-- 设备消息列 -->
<!-- TODO @AI可以在 data 里渲染么应该 antd 里有例子的 -->
<template #deviceMessage="{ row }"> <template #deviceMessage="{ row }">
<Popover <Popover
v-if="row.deviceMessage" v-if="row.deviceMessage"