Commit 9cd0bcf3af4c75e5b560559b55fb15abddb88897

Authored by ww
1 parent c3c429ae

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

... ... @@ -7,134 +7,125 @@ import { AlarmStatus } from '/@/enums/alarmEnum';
7 7 import { Tag } from 'ant-design-vue';
8 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 130 const handleAlarmStatus = (status: string) => {
140 131 return status.split('_').includes('ACTIVE');
... ...
... ... @@ -2,20 +2,28 @@
2 2 <BasicDrawer v-bind="$attrs" title="告警详情" @register="registerDrawer" width="30%">
3 3 <BasicForm @register="registerForm" />
4 4 <div class="flex justify-end">
  5 + <!-- [
  6 + '激活未确认: 可以处理,清除',
  7 + '激活已确认: 只可清除,已经处理',
  8 + '清除未确认: 只可处理,已经清除',
  9 + '清除已确认: 不需要做处理和清除',
  10 + ] -->
5 11 <a-button
6 12 type="primary"
7 13 class="mr-4"
8 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 19 <a-button
13 20 danger
14 21 type="primary"
15 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 27 </div>
20 28 </BasicDrawer>
21 29 </template>
... ... @@ -27,6 +35,7 @@
27 35 import { clearOrAckAlarm } from '/@/api/device/deviceManager';
28 36 import { alarmLevel, statusType } from '/@/views/device/list/config/detail.config';
29 37 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
  38 + import { AlarmStatus } from '/@/enums/alarmEnum';
30 39 export default defineComponent({
31 40 name: 'AlarmDetailDrawer',
32 41 components: {
... ... @@ -75,6 +84,7 @@
75 84 clearAlarm,
76 85 handleAlarm,
77 86 alarmStatus,
  87 + AlarmStatus,
78 88 };
79 89 },
80 90 });
... ...
... ... @@ -14,9 +14,9 @@
14 14 />
15 15 </template>
16 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 20 </template>
21 21 <template #toolbar>
22 22 <Tooltip>
... ... @@ -48,10 +48,10 @@
48 48 <AlarmDetailDrawer @register="registerDetailDrawer" @success="handleSuccess" />
49 49 </div>
50 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 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 55 import { doBatchAckAlarm, doBatchClearAlarm, getDeviceAlarm } from '/@/api/device/deviceManager';
56 56 import { useDrawer } from '/@/components/Drawer';
57 57 import AlarmDetailDrawer from './cpns/AlarmDetailDrawer.vue';
... ... @@ -69,223 +69,207 @@
69 69 import { useMessage } from '/@/hooks/web/useMessage';
70 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 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 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 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 9 width="80%"
10 10 >
11 11 <Tabs v-model:activeKey="activeKey" :size="size">
12   - <TabPane key="1" tab="详情">
  12 + <Tabs.TabPane key="1" tab="详情">
13 13 <Detail
14 14 ref="deviceDetailRef"
15 15 :deviceDetail="deviceDetail"
16 16 @open-gateway-device="handleOpenGatewayDevice"
17 17 />
18   - </TabPane>
19   - <TabPane key="modelOfMatter" tab="物模型数据">
  18 + </Tabs.TabPane>
  19 + <Tabs.TabPane key="modelOfMatter" tab="物模型数据">
20 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 26 <ChildDevice
34 27 :fromId="deviceDetail?.tbDeviceId"
35 28 @openTbDeviceDetail="handleOpenTbDeviceDetail"
36 29 />
37   - </TabPane>
38   - <TabPane key="7" tab="命令下发记录">
  30 + </Tabs.TabPane>
  31 + <Tabs.TabPane key="7" tab="命令下发记录">
39 32 <CommandRecord :deviceDetail="deviceDetail" :fromId="deviceDetail?.tbDeviceId" />
40   - </TabPane>
  33 + </Tabs.TabPane>
41 34 <!-- 网关设备并且场家是TBox -->
42   - <TabPane
  35 + <Tabs.TabPane
43 36 key="6"
44 37 tab="TBox"
45 38 v-if="deviceDetail?.deviceType === 'GATEWAY' && deviceDetail?.brand == 'TBox'"
46 39 >
47 40 <TBoxDetail :deviceDetail="deviceDetail" />
48   - </TabPane>
49   - <!-- 网关设备并且是TBox -->
50   -
51   - <TabPane key="eventManage" tab="事件管理">
  41 + </Tabs.TabPane>
  42 + <Tabs.TabPane key="eventManage" tab="事件管理">
52 43 <EventManage :tbDeviceId="deviceDetail.tbDeviceId" />
53   - </TabPane>
54   - <TabPane key="task" tab="任务">
  44 + </Tabs.TabPane>
  45 + <Tabs.TabPane key="task" tab="任务">
55 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 48 </Tabs>
61 49 </BasicDrawer>
62 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 53 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
66   -
67 54 import { Tabs } from 'ant-design-vue';
68 55 import Detail from '../tabs/Detail.vue';
69   - // import RealTimeData from '../tabs/RealTimeData.vue';
70   - import Alarm from '../tabs/Alarm.vue';
71 56 import ChildDevice from '../tabs/ChildDevice.vue';
72 57 import TBoxDetail from '../tabs/TBoxDetail.vue';
73 58 import { CommandRecord } from '../tabs/commandRecord/index';
74 59 import { getDeviceDetail } from '/@/api/device/deviceManager';
75   - // import HistoryData from '../tabs/HistoryData.vue';
76 60 import ModelOfMatter from '../tabs/ModelOfMatter.vue';
77 61 import EventManage from '../tabs/EventManage/index.vue';
78 62 import { DeviceRecord } from '/@/api/device/model/deviceModel';
79 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 102 </script>
... ...