Commit 9cd0bcf3af4c75e5b560559b55fb15abddb88897

Authored by ww
1 parent c3c429ae

perf: 优化告警记录清除与确认逻辑调整

@@ -7,134 +7,125 @@ import { AlarmStatus } from '/@/enums/alarmEnum'; @@ -7,134 +7,125 @@ import { AlarmStatus } from '/@/enums/alarmEnum';
7 import { Tag } from 'ant-design-vue'; 7 import { Tag } from 'ant-design-vue';
8 import { h } from 'vue'; 8 import { h } from 'vue';
9 9
10 -export const alarmSearchSchemas: FormSchema[] = [  
11 - {  
12 - field: 'status',  
13 - label: '告警状态',  
14 - component: 'Cascader',  
15 - colProps: { span: 6 },  
16 - componentProps: {  
17 - options: [  
18 - {  
19 - value: '0',  
20 - label: '清除',  
21 - children: [  
22 - {  
23 - value: AlarmStatus.CLEARED_UN_ACK,  
24 - label: '清除未确认',  
25 - },  
26 - {  
27 - value: AlarmStatus.CLEARED_ACK,  
28 - label: '清除已确认',  
29 - },  
30 - ],  
31 - },  
32 - {  
33 - value: '1',  
34 - label: '激活',  
35 - children: [  
36 - {  
37 - value: AlarmStatus.ACTIVE_UN_ACK,  
38 - label: '激活未确认',  
39 - },  
40 - {  
41 - value: AlarmStatus.ACTIVE_ACK,  
42 - label: '激活已确认',  
43 - },  
44 - ],  
45 - }, 10 +export const getAlarmSearchSchemas = (deviceAlaramDetailMode?: boolean): FormSchema[] => {
  11 + return [
  12 + {
  13 + field: 'status',
  14 + label: '告警/确认状态',
  15 + component: 'Cascader',
  16 + helpMessage: [
  17 + '激活未确认: 可以处理,清除',
  18 + '激活已确认: 只可清除,已经处理',
  19 + '清除未确认: 只可处理,已经清除',
  20 + '清除已确认: 不需要做处理和清除',
46 ], 21 ],
47 - // options: [  
48 - // {  
49 - // label: AlarmStatusMean[AlarmStatus.CLEARED_UN_ACK],  
50 - // value: AlarmStatus.CLEARED_UN_ACK,  
51 - // },  
52 - // {  
53 - // label: AlarmStatusMean[AlarmStatus.ACTIVE_UN_ACK],  
54 - // value: AlarmStatus.ACTIVE_UN_ACK,  
55 - // },  
56 - // {  
57 - // label: AlarmStatusMean[AlarmStatus.CLEARED_ACK],  
58 - // value: AlarmStatus.CLEARED_ACK,  
59 - // },  
60 - // {  
61 - // label: AlarmStatusMean[AlarmStatus.ACTIVE_ACK],  
62 - // value: AlarmStatus.ACTIVE_ACK,  
63 - // },  
64 - // ],  
65 - },  
66 - },  
67 - {  
68 - field: 'alarmType',  
69 - label: '告警场景',  
70 - component: 'Input',  
71 - colProps: { span: 6 },  
72 - componentProps: {  
73 - maxLength: 255,  
74 - placeholder: '请输入告警场景',  
75 - },  
76 - dynamicRules: () => {  
77 - return [  
78 - {  
79 - required: false,  
80 - validator: (_, value) => {  
81 - if (String(value).length > 255) {  
82 - return Promise.reject('字数不超过255个字');  
83 - }  
84 - return Promise.resolve(); 22 + componentProps: {
  23 + popupClassName: 'alarm-stauts-cascader',
  24 + options: [
  25 + {
  26 + value: '0',
  27 + label: '清除',
  28 + children: [
  29 + {
  30 + value: AlarmStatus.CLEARED_UN_ACK,
  31 + label: '清除未确认',
  32 + },
  33 + {
  34 + value: AlarmStatus.CLEARED_ACK,
  35 + label: '清除已确认',
  36 + },
  37 + ],
85 }, 38 },
86 - },  
87 - ]; 39 + {
  40 + value: '1',
  41 + label: '激活',
  42 + children: [
  43 + {
  44 + value: AlarmStatus.ACTIVE_UN_ACK,
  45 + label: '激活未确认',
  46 + },
  47 + {
  48 + value: AlarmStatus.ACTIVE_ACK,
  49 + label: '激活已确认',
  50 + },
  51 + ],
  52 + },
  53 + ],
  54 + placeholder: '请选择告警/确认状态',
  55 + },
88 }, 56 },
89 - },  
90 - {  
91 - field: 'deviceName',  
92 - label: '告警设备',  
93 - component: 'Input',  
94 - colProps: { span: 6 },  
95 - componentProps: {  
96 - maxLength: 255,  
97 - placeholder: '请输入告警设备', 57 + {
  58 + field: 'alarmType',
  59 + label: '告警场景',
  60 + component: 'Input',
  61 + componentProps: {
  62 + maxLength: 255,
  63 + placeholder: '请输入告警场景',
  64 + },
  65 + dynamicRules: () => {
  66 + return [
  67 + {
  68 + required: false,
  69 + validator: (_, value) => {
  70 + if (String(value).length > 255) {
  71 + return Promise.reject('字数不超过255个字');
  72 + }
  73 + return Promise.resolve();
  74 + },
  75 + },
  76 + ];
  77 + },
98 }, 78 },
99 - dynamicRules: () => {  
100 - return [  
101 - {  
102 - required: false,  
103 - validator: (_, value) => {  
104 - if (String(value).length > 255) {  
105 - return Promise.reject('字数不超过255个字');  
106 - }  
107 - return Promise.resolve(); 79 + {
  80 + field: 'deviceName',
  81 + label: '告警设备',
  82 + component: 'Input',
  83 + componentProps: {
  84 + maxLength: 255,
  85 + placeholder: '请输入告警设备',
  86 + },
  87 + ifShow: () => !deviceAlaramDetailMode,
  88 + dynamicRules: () => {
  89 + return [
  90 + {
  91 + required: false,
  92 + validator: (_, value) => {
  93 + if (String(value).length > 255) {
  94 + return Promise.reject('字数不超过255个字');
  95 + }
  96 + return Promise.resolve();
  97 + },
108 }, 98 },
109 - },  
110 - ]; 99 + ];
  100 + },
111 }, 101 },
112 - },  
113 - {  
114 - field: 'severity',  
115 - label: '告警级别',  
116 - component: 'ApiSelect',  
117 - colProps: { span: 6 },  
118 - componentProps: {  
119 - placeholder: '请选择告警级别',  
120 - api: findDictItemByCode,  
121 - params: {  
122 - dictCode: 'severity_type', 102 + {
  103 + field: 'severity',
  104 + label: '告警级别',
  105 + component: 'ApiSelect',
  106 + componentProps: {
  107 + placeholder: '请选择告警级别',
  108 + api: findDictItemByCode,
  109 + params: {
  110 + dictCode: 'severity_type',
  111 + },
  112 + labelField: 'itemText',
  113 + valueField: 'itemValue',
123 }, 114 },
124 - labelField: 'itemText',  
125 - valueField: 'itemValue',  
126 }, 115 },
127 - },  
128 - {  
129 - field: 'alarmTime',  
130 - label: '告警时间',  
131 - component: 'RangePicker',  
132 - componentProps: {  
133 - showTime: { defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')] }, 116 + {
  117 + field: 'alarmTime',
  118 + label: '告警时间',
  119 + component: 'RangePicker',
  120 + colProps: { span: 12 },
  121 + componentProps: {
  122 + showTime: {
  123 + defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
  124 + },
  125 + },
134 }, 126 },
135 - colProps: { span: 6 },  
136 - },  
137 -]; 127 + ];
  128 +};
138 129
139 const handleAlarmStatus = (status: string) => { 130 const handleAlarmStatus = (status: string) => {
140 return status.split('_').includes('ACTIVE'); 131 return status.split('_').includes('ACTIVE');
@@ -2,20 +2,28 @@ @@ -2,20 +2,28 @@
2 <BasicDrawer v-bind="$attrs" title="告警详情" @register="registerDrawer" width="30%"> 2 <BasicDrawer v-bind="$attrs" title="告警详情" @register="registerDrawer" width="30%">
3 <BasicForm @register="registerForm" /> 3 <BasicForm @register="registerForm" />
4 <div class="flex justify-end"> 4 <div class="flex justify-end">
  5 + <!-- [
  6 + '激活未确认: 可以处理,清除',
  7 + '激活已确认: 只可清除,已经处理',
  8 + '清除未确认: 只可处理,已经清除',
  9 + '清除已确认: 不需要做处理和清除',
  10 + ] -->
5 <a-button 11 <a-button
6 type="primary" 12 type="primary"
7 class="mr-4" 13 class="mr-4"
8 @click="handleAlarm" 14 @click="handleAlarm"
9 - v-if="alarmStatus !== 'ACTIVE_ACK' && alarmStatus !== 'CLEARED_ACK'"  
10 - >处理</a-button 15 + v-if="alarmStatus !== AlarmStatus.ACTIVE_ACK && alarmStatus !== AlarmStatus.CLEARED_ACK"
11 > 16 >
  17 + 处理
  18 + </a-button>
12 <a-button 19 <a-button
13 danger 20 danger
14 type="primary" 21 type="primary"
15 @click="clearAlarm" 22 @click="clearAlarm"
16 - v-if="alarmStatus !== 'CLEARED_UNACK' && alarmStatus !== 'CLEARED_ACK'"  
17 - >清除</a-button 23 + v-if="alarmStatus === AlarmStatus.ACTIVE_ACK"
18 > 24 >
  25 + 清除
  26 + </a-button>
19 </div> 27 </div>
20 </BasicDrawer> 28 </BasicDrawer>
21 </template> 29 </template>
@@ -27,6 +35,7 @@ @@ -27,6 +35,7 @@
27 import { clearOrAckAlarm } from '/@/api/device/deviceManager'; 35 import { clearOrAckAlarm } from '/@/api/device/deviceManager';
28 import { alarmLevel, statusType } from '/@/views/device/list/config/detail.config'; 36 import { alarmLevel, statusType } from '/@/views/device/list/config/detail.config';
29 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; 37 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
  38 + import { AlarmStatus } from '/@/enums/alarmEnum';
30 export default defineComponent({ 39 export default defineComponent({
31 name: 'AlarmDetailDrawer', 40 name: 'AlarmDetailDrawer',
32 components: { 41 components: {
@@ -75,6 +84,7 @@ @@ -75,6 +84,7 @@
75 clearAlarm, 84 clearAlarm,
76 handleAlarm, 85 handleAlarm,
77 alarmStatus, 86 alarmStatus,
  87 + AlarmStatus,
78 }; 88 };
79 }, 89 },
80 }); 90 });
@@ -14,9 +14,9 @@ @@ -14,9 +14,9 @@
14 /> 14 />
15 </template> 15 </template>
16 <template #details="{ record }"> 16 <template #details="{ record }">
17 - <a-button type="link" class="ml-2" @click="handleViewAlarmDetails(record)"> 17 + <Button type="link" class="ml-2" @click="handleViewAlarmDetails(record)">
18 查看告警详情 18 查看告警详情
19 - </a-button> 19 + </Button>
20 </template> 20 </template>
21 <template #toolbar> 21 <template #toolbar>
22 <Tooltip> 22 <Tooltip>
@@ -48,10 +48,10 @@ @@ -48,10 +48,10 @@
48 <AlarmDetailDrawer @register="registerDetailDrawer" @success="handleSuccess" /> 48 <AlarmDetailDrawer @register="registerDetailDrawer" @success="handleSuccess" />
49 </div> 49 </div>
50 </template> 50 </template>
51 -<script lang="ts">  
52 - import { defineComponent, nextTick, h, computed } from 'vue'; 51 +<script lang="ts" setup>
  52 + import { nextTick, h, computed } from 'vue';
53 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 53 import { BasicTable, useTable, TableAction } from '/@/components/Table';
54 - import { alarmColumns, alarmSearchSchemas } from './config/detail.config'; 54 + import { alarmColumns, getAlarmSearchSchemas } from './config/detail.config';
55 import { doBatchAckAlarm, doBatchClearAlarm, getDeviceAlarm } from '/@/api/device/deviceManager'; 55 import { doBatchAckAlarm, doBatchClearAlarm, getDeviceAlarm } from '/@/api/device/deviceManager';
56 import { useDrawer } from '/@/components/Drawer'; 56 import { useDrawer } from '/@/components/Drawer';
57 import AlarmDetailDrawer from './cpns/AlarmDetailDrawer.vue'; 57 import AlarmDetailDrawer from './cpns/AlarmDetailDrawer.vue';
@@ -69,223 +69,207 @@ @@ -69,223 +69,207 @@
69 import { useMessage } from '/@/hooks/web/useMessage'; 69 import { useMessage } from '/@/hooks/web/useMessage';
70 import { QuestionCircleOutlined } from '@ant-design/icons-vue'; 70 import { QuestionCircleOutlined } from '@ant-design/icons-vue';
71 71
72 - export default defineComponent({  
73 - name: 'AlarmCenter',  
74 - components: {  
75 - Button,  
76 - BasicTable,  
77 - TableAction,  
78 - AlarmDetailDrawer,  
79 - QuestionCircleOutlined,  
80 - Tooltip,  
81 - }, 72 + const props = defineProps<{
  73 + deviceId?: string;
  74 + }>();
82 75
83 - setup() {  
84 - const [registerTable, { reload, getSelectRows, clearSelectedRowKeys, getRowSelection }] =  
85 - useTable({  
86 - title: '告警记录列表',  
87 - api: getDeviceAlarm,  
88 - beforeFetch: (params) => {  
89 - const { status } = params;  
90 - const obj = {  
91 - ...params,  
92 - ...{  
93 - status: status ? status.at(-1) : null,  
94 - },  
95 - };  
96 - return obj; 76 + const [registerTable, { reload, getSelectRows, clearSelectedRowKeys, getRowSelection }] =
  77 + useTable({
  78 + title: '告警记录列表',
  79 + api: getDeviceAlarm,
  80 + beforeFetch: (params) => {
  81 + const { status } = params;
  82 + const obj = {
  83 + ...params,
  84 + ...{
  85 + status: status ? status.at(-1) : null,
97 }, 86 },
98 - columns: alarmColumns,  
99 - rowKey: 'id',  
100 - useSearchForm: true,  
101 - formConfig: {  
102 - labelWidth: 120,  
103 - schemas: alarmSearchSchemas,  
104 - fieldMapToTime: [['alarmTime', ['startTime', 'endTime'], 'x']],  
105 - },  
106 - bordered: true,  
107 - showIndexColumn: false,  
108 - showTableSetting: true,  
109 - clickToRowSelect: false,  
110 - rowSelection: {  
111 - type: 'checkbox',  
112 - getCheckboxProps: (record: AlarmLogItem) => {  
113 - return {  
114 - disabled: record.status === AlarmStatus.CLEARED_ACK,  
115 - };  
116 - },  
117 - },  
118 - actionColumn: {  
119 - width: 200,  
120 - title: '操作',  
121 - slots: { customRender: 'action' },  
122 - fixed: 'right',  
123 - },  
124 - });  
125 - const [registerDetailDrawer, { openDrawer }] = useDrawer();  
126 - const handleDetail = (record: Recordable) => {  
127 - openDrawer(true, record);  
128 - };  
129 - const handleSuccess = () => {  
130 - reload();  
131 - }; 87 + };
  88 + return obj;
  89 + },
  90 + columns: alarmColumns,
  91 + rowKey: 'id',
  92 + useSearchForm: true,
  93 + formConfig: {
  94 + labelWidth: 120,
  95 + schemas: getAlarmSearchSchemas(!!props.deviceId),
  96 + fieldMapToTime: [['alarmTime', ['startTime', 'endTime'], 'x']],
  97 + baseColProps: { span: 8 },
  98 + },
  99 + bordered: true,
  100 + showIndexColumn: false,
  101 + showTableSetting: true,
  102 + clickToRowSelect: false,
  103 + searchInfo: {
  104 + deviceId: props.deviceId,
  105 + },
  106 + rowSelection: {
  107 + type: 'checkbox',
  108 + getCheckboxProps: (record: AlarmLogItem) => {
  109 + return {
  110 + disabled: record.status === AlarmStatus.CLEARED_ACK,
  111 + };
  112 + },
  113 + },
  114 + actionColumn: {
  115 + width: 200,
  116 + title: '操作',
  117 + slots: { customRender: 'action' },
  118 + fixed: 'right',
  119 + },
  120 + });
  121 + const [registerDetailDrawer, { openDrawer }] = useDrawer();
  122 + const handleDetail = (record: Recordable) => {
  123 + openDrawer(true, record);
  124 + };
  125 + const handleSuccess = () => {
  126 + reload();
  127 + };
132 128
133 - const findName = (item: Recordable, curr: Recordable) => {  
134 - return item.attribute.find((item) => item.identifier === curr?.key)?.name;  
135 - }; 129 + const findName = (item: Recordable, curr: Recordable) => {
  130 + return item.attribute.find((item) => item.identifier === curr?.key)?.name;
  131 + };
136 132
137 - const findLogin = (curr: Recordable) => {  
138 - return [...operationNumber_OR_TIME, ...operationString, ...operationBoolean].find(  
139 - (item) => item.value === curr?.logic  
140 - )?.symbol;  
141 - }; 133 + const findLogin = (curr: Recordable) => {
  134 + return [...operationNumber_OR_TIME, ...operationString, ...operationBoolean].find(
  135 + (item) => item.value === curr?.logic
  136 + )?.symbol;
  137 + };
142 138
143 - const findAttribute = (item: Recordable, curr: Recordable) => {  
144 - item.attribute.find((findItem) => findItem.identifier === curr?.key);  
145 - }; 139 + const findAttribute = (item: Recordable, curr: Recordable) => {
  140 + item.attribute.find((findItem) => findItem.identifier === curr?.key);
  141 + };
146 142
147 - const findValue = (item: Recordable, curr: Recordable) => {  
148 - return {  
149 - ['触发属性']: findName(item, curr),  
150 - ['触发条件']: `${findLogin(curr)}${curr?.logicValue}`,  
151 - ['触发值']: `${curr?.realValue}${  
152 - findAttribute(item, curr)?.detail?.dataType?.specs?.unit?.key ?? ''  
153 - }`,  
154 - };  
155 - }; 143 + const findValue = (item: Recordable, curr: Recordable) => {
  144 + return {
  145 + ['触发属性']: findName(item, curr),
  146 + ['触发条件']: `${findLogin(curr)}${curr?.logicValue}`,
  147 + ['触发值']: `${curr?.realValue}${
  148 + findAttribute(item, curr)?.detail?.dataType?.specs?.unit?.key ?? ''
  149 + }`,
  150 + };
  151 + };
156 152
157 - const handleAlarmText = (text: string) => (text === 'triggerData' ? '触发器' : '执行条件'); 153 + const handleAlarmText = (text: string) => (text === 'triggerData' ? '触发器' : '执行条件');
158 154
159 - const handleViewAlarmDetails = async (record: Recordable) => {  
160 - await nextTick();  
161 - const { details } = record;  
162 - if (!details) return;  
163 - const deviceIdKeys = Object.keys(details);  
164 - const dataFormat = await handleAlarmDetailFormat(deviceIdKeys);  
165 - const mapDataFormat = deviceIdKeys.map((deviceKey: string) => {  
166 - const findDataFormat = dataFormat.find(  
167 - (dataItem: Recordable) => dataItem.tbDeviceId === deviceKey  
168 - );  
169 - const dataKeys = Object.keys(details[deviceKey]);  
170 - const data: any = dataKeys.map((dataItem: string) => {  
171 - if (dataItem !== 'triggerData' && dataItem !== 'conditionData') {  
172 - return findValue(findDataFormat, details[deviceKey]);  
173 - } else {  
174 - return {  
175 - [handleAlarmText(dataItem)]: findValue(  
176 - findDataFormat,  
177 - details[deviceKey][dataItem]  
178 - ),  
179 - };  
180 - }  
181 - });  
182 - const objectDataFormat = data.reduce((acc: Recordable, curr: Recordable) => {  
183 - return {  
184 - ...acc,  
185 - ...curr,  
186 - };  
187 - });  
188 - return {  
189 - [findDataFormat.name]: objectDataFormat,  
190 - };  
191 - });  
192 - const objectDataFormats = mapDataFormat.reduce((acc: Recordable, curr: Recordable) => { 155 + const handleViewAlarmDetails = async (record: Recordable) => {
  156 + await nextTick();
  157 + const { details } = record;
  158 + if (!details) return;
  159 + const deviceIdKeys = Object.keys(details);
  160 + const dataFormat = await handleAlarmDetailFormat(deviceIdKeys);
  161 + const mapDataFormat = deviceIdKeys.map((deviceKey: string) => {
  162 + const findDataFormat = dataFormat.find(
  163 + (dataItem: Recordable) => dataItem.tbDeviceId === deviceKey
  164 + );
  165 + const dataKeys = Object.keys(details[deviceKey]);
  166 + const data: any = dataKeys.map((dataItem: string) => {
  167 + if (dataItem !== 'triggerData' && dataItem !== 'conditionData') {
  168 + return findValue(findDataFormat, details[deviceKey]);
  169 + } else {
193 return { 170 return {
194 - ...acc,  
195 - ...curr, 171 + [handleAlarmText(dataItem)]: findValue(findDataFormat, details[deviceKey][dataItem]),
196 }; 172 };
197 - });  
198 - Modal.info({  
199 - title: '告警详情',  
200 - width: 600,  
201 - centered: true,  
202 - maskClosable: true,  
203 - content: h(JsonPreview, { data: JSON.parse(JSON.stringify(objectDataFormats)), deep: 4 }),  
204 - });  
205 - };  
206 - const handleAlarmDetailFormat = async (keys: string[]) => {  
207 - const temp: Recordable = [];  
208 - for (let item of keys) {  
209 - if (item === 'key' || item === 'data') return []; //旧数据则终止  
210 - const deviceDetailRes = await getDeviceDetail(item);  
211 - const { deviceProfileId } = deviceDetailRes;  
212 - if (!deviceProfileId) return [];  
213 - const attributeRes = await getAttribute(deviceProfileId);  
214 - const dataFormat: Recordable = handleDataFormat(deviceDetailRes, attributeRes);  
215 - temp.push(dataFormat);  
216 } 173 }
217 - return temp;  
218 - };  
219 - const handleDataFormat = (deviceDetail: Recordable, attributes: Recordable) => {  
220 - const { name, tbDeviceId, alias } = deviceDetail;  
221 - const attribute = attributes.map((item) => ({  
222 - identifier: item.identifier,  
223 - name: item.name,  
224 - detail: item.detail,  
225 - })); 174 + });
  175 + const objectDataFormat = data.reduce((acc: Recordable, curr: Recordable) => {
226 return { 176 return {
227 - name: alias || name,  
228 - tbDeviceId,  
229 - attribute, 177 + ...acc,
  178 + ...curr,
230 }; 179 };
  180 + });
  181 + return {
  182 + [findDataFormat.name]: objectDataFormat,
231 }; 183 };
  184 + });
  185 + const objectDataFormats = mapDataFormat.reduce((acc: Recordable, curr: Recordable) => {
  186 + return {
  187 + ...acc,
  188 + ...curr,
  189 + };
  190 + });
  191 + Modal.info({
  192 + title: '告警详情',
  193 + width: 600,
  194 + centered: true,
  195 + maskClosable: true,
  196 + content: h(JsonPreview, { data: JSON.parse(JSON.stringify(objectDataFormats)), deep: 4 }),
  197 + });
  198 + };
  199 + const handleAlarmDetailFormat = async (keys: string[]) => {
  200 + const temp: Recordable = [];
  201 + for (let item of keys) {
  202 + if (item === 'key' || item === 'data') return []; //旧数据则终止
  203 + const deviceDetailRes = await getDeviceDetail(item);
  204 + const { deviceProfileId } = deviceDetailRes;
  205 + if (!deviceProfileId) return [];
  206 + const attributeRes = await getAttribute(deviceProfileId);
  207 + const dataFormat: Recordable = handleDataFormat(deviceDetailRes, attributeRes);
  208 + temp.push(dataFormat);
  209 + }
  210 + return temp;
  211 + };
  212 + const handleDataFormat = (deviceDetail: Recordable, attributes: Recordable) => {
  213 + const { name, tbDeviceId, alias } = deviceDetail;
  214 + const attribute = attributes.map((item) => ({
  215 + identifier: item.identifier,
  216 + name: item.name,
  217 + detail: item.detail,
  218 + }));
  219 + return {
  220 + name: alias || name,
  221 + tbDeviceId,
  222 + attribute,
  223 + };
  224 + };
232 225
233 - const getCanBatchClear = computed(() => {  
234 - const rowSelection = getRowSelection();  
235 - const getRows: AlarmLogItem[] = getSelectRows(); 226 + const getCanBatchClear = computed(() => {
  227 + const rowSelection = getRowSelection();
  228 + const getRows: AlarmLogItem[] = getSelectRows();
236 229
237 - return (  
238 - !rowSelection.selectedRowKeys?.length ||  
239 - getRows.some(  
240 - (item) =>  
241 - item.status === AlarmStatus.CLEARED_ACK || item.status === AlarmStatus.CLEARED_UN_ACK  
242 - )  
243 - );  
244 - }); 230 + return (
  231 + !rowSelection.selectedRowKeys?.length ||
  232 + !getRows.every((item) => item.status === AlarmStatus.ACTIVE_ACK)
  233 + );
  234 + });
245 235
246 - const getCanBatchAck = computed(() => {  
247 - const rowSelection = getRowSelection();  
248 - const getRows: AlarmLogItem[] = getSelectRows(); 236 + const getCanBatchAck = computed(() => {
  237 + const rowSelection = getRowSelection();
  238 + const getRows: AlarmLogItem[] = getSelectRows();
249 239
250 - return (  
251 - !rowSelection.selectedRowKeys?.length ||  
252 - getRows.some(  
253 - (item) =>  
254 - item.status === AlarmStatus.CLEARED_ACK || item.status === AlarmStatus.ACTIVE_ACK  
255 - )  
256 - );  
257 - });  
258 -  
259 - const { createMessage } = useMessage();  
260 - const handleBatchAck = async () => {  
261 - const ids = getSelectRows<AlarmLogItem>().map((item) => item.id);  
262 - if (!ids.length) return;  
263 - await doBatchAckAlarm(ids);  
264 - createMessage.success('操作成功');  
265 - clearSelectedRowKeys();  
266 - reload();  
267 - }; 240 + return (
  241 + !rowSelection.selectedRowKeys?.length ||
  242 + !getRows.every(
  243 + (item) =>
  244 + item.status === AlarmStatus.ACTIVE_UN_ACK || item.status === AlarmStatus.CLEARED_UN_ACK
  245 + )
  246 + );
  247 + });
268 248
269 - const handleBatchClear = async () => {  
270 - const ids = getSelectRows<AlarmLogItem>().map((item) => item.id);  
271 - if (!ids.length) return;  
272 - await doBatchClearAlarm(ids);  
273 - createMessage.success('操作成功');  
274 - clearSelectedRowKeys();  
275 - reload();  
276 - }; 249 + const { createMessage } = useMessage();
  250 + const handleBatchAck = async () => {
  251 + const ids = getSelectRows<AlarmLogItem>().map((item) => item.id);
  252 + if (!ids.length) return;
  253 + await doBatchAckAlarm(ids);
  254 + createMessage.success('操作成功');
  255 + clearSelectedRowKeys();
  256 + reload();
  257 + };
277 258
278 - return {  
279 - registerTable,  
280 - registerDetailDrawer,  
281 - handleDetail,  
282 - handleSuccess,  
283 - handleViewAlarmDetails,  
284 - handleBatchAck,  
285 - handleBatchClear,  
286 - getCanBatchAck,  
287 - getCanBatchClear,  
288 - };  
289 - },  
290 - }); 259 + const handleBatchClear = async () => {
  260 + const ids = getSelectRows<AlarmLogItem>().map((item) => item.id);
  261 + if (!ids.length) return;
  262 + await doBatchClearAlarm(ids);
  263 + createMessage.success('操作成功');
  264 + clearSelectedRowKeys();
  265 + reload();
  266 + };
291 </script> 267 </script>
  268 +
  269 +<style>
  270 + .alarm-stauts-cascader {
  271 + .ant-cascader-menu {
  272 + height: fit-content;
  273 + }
  274 + }
  275 +</style>
@@ -9,145 +9,94 @@ @@ -9,145 +9,94 @@
9 width="80%" 9 width="80%"
10 > 10 >
11 <Tabs v-model:activeKey="activeKey" :size="size"> 11 <Tabs v-model:activeKey="activeKey" :size="size">
12 - <TabPane key="1" tab="详情"> 12 + <Tabs.TabPane key="1" tab="详情">
13 <Detail 13 <Detail
14 ref="deviceDetailRef" 14 ref="deviceDetailRef"
15 :deviceDetail="deviceDetail" 15 :deviceDetail="deviceDetail"
16 @open-gateway-device="handleOpenGatewayDevice" 16 @open-gateway-device="handleOpenGatewayDevice"
17 /> 17 />
18 - </TabPane>  
19 - <TabPane key="modelOfMatter" tab="物模型数据"> 18 + </Tabs.TabPane>
  19 + <Tabs.TabPane key="modelOfMatter" tab="物模型数据">
20 <ModelOfMatter :deviceDetail="deviceDetail" /> 20 <ModelOfMatter :deviceDetail="deviceDetail" />
21 - </TabPane>  
22 - <!-- <TabPane key="2" tab="实时数据" v-if="deviceDetail?.deviceType !== 'GATEWAY'">  
23 - <RealTimeData :deviceDetail="deviceDetail" />  
24 - </TabPane>  
25 - <TabPane key="7" tab="历史数据" v-if="deviceDetail?.deviceType !== 'GATEWAY'">  
26 - <HistoryData :deviceDetail="deviceDetail" />  
27 - </TabPane> -->  
28 - <!-- <TabPane key="5" tab="命令下发" v-if="deviceDetail?.deviceType !== 'SENSOR'">  
29 - <CommandIssuance :deviceDetail="deviceDetail" />  
30 - </TabPane> -->  
31 - <TabPane key="3" tab="告警"><Alarm :id="deviceDetail.id" /></TabPane>  
32 - <TabPane key="4" tab="子设备" v-if="deviceDetail?.deviceType === 'GATEWAY'"> 21 + </Tabs.TabPane>
  22 + <Tabs.TabPane key="3" tab="告警">
  23 + <AlarmLog :device-id="deviceDetail.id" class="bg-gray-100" />
  24 + </Tabs.TabPane>
  25 + <Tabs.TabPane key="4" tab="子设备" v-if="deviceDetail?.deviceType === 'GATEWAY'">
33 <ChildDevice 26 <ChildDevice
34 :fromId="deviceDetail?.tbDeviceId" 27 :fromId="deviceDetail?.tbDeviceId"
35 @openTbDeviceDetail="handleOpenTbDeviceDetail" 28 @openTbDeviceDetail="handleOpenTbDeviceDetail"
36 /> 29 />
37 - </TabPane>  
38 - <TabPane key="7" tab="命令下发记录"> 30 + </Tabs.TabPane>
  31 + <Tabs.TabPane key="7" tab="命令下发记录">
39 <CommandRecord :deviceDetail="deviceDetail" :fromId="deviceDetail?.tbDeviceId" /> 32 <CommandRecord :deviceDetail="deviceDetail" :fromId="deviceDetail?.tbDeviceId" />
40 - </TabPane> 33 + </Tabs.TabPane>
41 <!-- 网关设备并且场家是TBox --> 34 <!-- 网关设备并且场家是TBox -->
42 - <TabPane 35 + <Tabs.TabPane
43 key="6" 36 key="6"
44 tab="TBox" 37 tab="TBox"
45 v-if="deviceDetail?.deviceType === 'GATEWAY' && deviceDetail?.brand == 'TBox'" 38 v-if="deviceDetail?.deviceType === 'GATEWAY' && deviceDetail?.brand == 'TBox'"
46 > 39 >
47 <TBoxDetail :deviceDetail="deviceDetail" /> 40 <TBoxDetail :deviceDetail="deviceDetail" />
48 - </TabPane>  
49 - <!-- 网关设备并且是TBox -->  
50 -  
51 - <TabPane key="eventManage" tab="事件管理"> 41 + </Tabs.TabPane>
  42 + <Tabs.TabPane key="eventManage" tab="事件管理">
52 <EventManage :tbDeviceId="deviceDetail.tbDeviceId" /> 43 <EventManage :tbDeviceId="deviceDetail.tbDeviceId" />
53 - </TabPane>  
54 - <TabPane key="task" tab="任务"> 44 + </Tabs.TabPane>
  45 + <Tabs.TabPane key="task" tab="任务">
55 <Task :tbDeviceId="deviceDetail.tbDeviceId" /> 46 <Task :tbDeviceId="deviceDetail.tbDeviceId" />
56 - </TabPane>  
57 - <!-- <TabPane v-if="false" key="videoChannel" tab="视频通道">  
58 - <VideoChannel :deviceDetail="deviceDetail" :fromId="deviceDetail?.tbDeviceId" />  
59 - </TabPane> --> 47 + </Tabs.TabPane>
60 </Tabs> 48 </Tabs>
61 </BasicDrawer> 49 </BasicDrawer>
62 </template> 50 </template>
63 -<script lang="ts">  
64 - import { defineComponent, ref, computed } from 'vue'; 51 +<script lang="ts" setup>
  52 + import { ref, computed } from 'vue';
65 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; 53 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
66 -  
67 import { Tabs } from 'ant-design-vue'; 54 import { Tabs } from 'ant-design-vue';
68 import Detail from '../tabs/Detail.vue'; 55 import Detail from '../tabs/Detail.vue';
69 - // import RealTimeData from '../tabs/RealTimeData.vue';  
70 - import Alarm from '../tabs/Alarm.vue';  
71 import ChildDevice from '../tabs/ChildDevice.vue'; 56 import ChildDevice from '../tabs/ChildDevice.vue';
72 import TBoxDetail from '../tabs/TBoxDetail.vue'; 57 import TBoxDetail from '../tabs/TBoxDetail.vue';
73 import { CommandRecord } from '../tabs/commandRecord/index'; 58 import { CommandRecord } from '../tabs/commandRecord/index';
74 import { getDeviceDetail } from '/@/api/device/deviceManager'; 59 import { getDeviceDetail } from '/@/api/device/deviceManager';
75 - // import HistoryData from '../tabs/HistoryData.vue';  
76 import ModelOfMatter from '../tabs/ModelOfMatter.vue'; 60 import ModelOfMatter from '../tabs/ModelOfMatter.vue';
77 import EventManage from '../tabs/EventManage/index.vue'; 61 import EventManage from '../tabs/EventManage/index.vue';
78 import { DeviceRecord } from '/@/api/device/model/deviceModel'; 62 import { DeviceRecord } from '/@/api/device/model/deviceModel';
79 import Task from '../tabs/Task.vue'; 63 import Task from '../tabs/Task.vue';
80 - // import { VideoChannel } from '../tabs/VideoChannel/index'; 64 + import AlarmLog from '/@/views/alarm/log/index.vue';
81 65
82 - export default defineComponent({  
83 - name: 'DeviceModal',  
84 - components: {  
85 - BasicDrawer,  
86 - Tabs,  
87 - TabPane: Tabs.TabPane,  
88 - Detail,  
89 - // RealTimeData,  
90 - Alarm,  
91 - ChildDevice,  
92 - TBoxDetail,  
93 - // HistoryData,  
94 - ModelOfMatter,  
95 - CommandRecord,  
96 - EventManage,  
97 - Task,  
98 - // VideoChannel,  
99 - },  
100 - emits: ['reload', 'register', 'openTbDeviceDetail', 'openGatewayDeviceDetail'],  
101 - setup(_props, { emit }) {  
102 - const activeKey = ref('1');  
103 - const size = ref('small');  
104 - const deviceDetailRef = ref();  
105 - const deviceDetail = ref<DeviceRecord>({} as unknown as DeviceRecord);  
106 - const tbDeviceId = ref(''); 66 + const emit = defineEmits(['reload', 'register', 'openTbDeviceDetail', 'openGatewayDeviceDetail']);
107 67
108 - const isTransportType = ref<Boolean>(false); //获取产品是不是GB/T 28181  
109 - // 详情回显  
110 - const [register] = useDrawerInner(async (data) => {  
111 - const { id, transportType, deviceType } = data || {};  
112 - isTransportType.value =  
113 - transportType == 'GB/T28181' && deviceType == 'DIRECT_CONNECTION' ? true : false;  
114 - // 设备详情  
115 - const res = await getDeviceDetail(id);  
116 - deviceDetail.value = res;  
117 - const { latitude, longitude, address } = res.deviceInfo || {};  
118 - if (latitude) {  
119 - deviceDetailRef.value.initMap(longitude, latitude, address);  
120 - }  
121 - });  
122 - const closeDrawer = () => {  
123 - activeKey.value = '1';  
124 - }; 68 + const activeKey = ref('1');
  69 + const size = ref('small');
  70 + const deviceDetailRef = ref();
  71 + const deviceDetail = ref<DeviceRecord>({} as unknown as DeviceRecord);
125 72
126 - const handleOpenTbDeviceDetail = (data: { id: string; tbDeviceId: string }) => {  
127 - emit('openTbDeviceDetail', data);  
128 - }; 73 + const isTransportType = ref<Boolean>(false); //获取产品是不是GB/T 28181
  74 + // 详情回显
  75 + const [register] = useDrawerInner(async (data) => {
  76 + const { id, transportType, deviceType } = data || {};
  77 + isTransportType.value =
  78 + transportType == 'GB/T28181' && deviceType == 'DIRECT_CONNECTION' ? true : false;
  79 + // 设备详情
  80 + const res = await getDeviceDetail(id);
  81 + deviceDetail.value = res;
  82 + const { latitude, longitude, address } = res.deviceInfo || {};
  83 + if (latitude) {
  84 + deviceDetailRef.value.initMap(longitude, latitude, address);
  85 + }
  86 + });
  87 + const closeDrawer = () => {
  88 + activeKey.value = '1';
  89 + };
129 90
130 - const handleOpenGatewayDevice = (data: { gatewayId: string; tbDeviceId: string }) => {  
131 - emit('openGatewayDeviceDetail', { id: data.gatewayId });  
132 - }; 91 + const handleOpenTbDeviceDetail = (data: { id: string; tbDeviceId: string }) => {
  92 + emit('openTbDeviceDetail', data);
  93 + };
133 94
134 - const drawerTitle = computed(() => {  
135 - return deviceDetail.value?.alias || deviceDetail.value?.name;  
136 - }); 95 + const handleOpenGatewayDevice = (data: { gatewayId: string; tbDeviceId: string }) => {
  96 + emit('openGatewayDeviceDetail', { id: data.gatewayId });
  97 + };
137 98
138 - return {  
139 - size,  
140 - activeKey,  
141 - register,  
142 - closeDrawer,  
143 - deviceDetail,  
144 - deviceDetailRef,  
145 - tbDeviceId,  
146 - handleOpenTbDeviceDetail,  
147 - handleOpenGatewayDevice,  
148 - isTransportType,  
149 - drawerTitle,  
150 - };  
151 - }, 99 + const drawerTitle = computed(() => {
  100 + return deviceDetail.value?.alias || deviceDetail.value?.name;
152 }); 101 });
153 </script> 102 </script>