Commit 69e227acdd81d26253751ad1a2fe7b9a97dda826
Merge branch 'sqy_dev' into 'main'
feat:实时数据,告警... See merge request huang/yun-teng-iot-front!52
Showing
10 changed files
with
323 additions
and
73 deletions
| @@ -103,3 +103,15 @@ export const getDeviceAlarm = (params?: DeviceProfileQueryParam) => { | @@ -103,3 +103,15 @@ export const getDeviceAlarm = (params?: DeviceProfileQueryParam) => { | ||
| 103 | params, | 103 | params, |
| 104 | }); | 104 | }); |
| 105 | }; | 105 | }; |
| 106 | + | ||
| 107 | +// 如果是flag为true 就是清除报警,否则是处理报警 | ||
| 108 | +export const clearOrAckAlarm = (id: string, flag: boolean) => { | ||
| 109 | + return defHttp.post( | ||
| 110 | + { | ||
| 111 | + url: `${DeviceManagerApi.DEVICE_ALARM_URL}/${id}/${flag ? 'clear' : 'ack'}`, | ||
| 112 | + }, | ||
| 113 | + { | ||
| 114 | + joinPrefix: false, | ||
| 115 | + } | ||
| 116 | + ); | ||
| 117 | +}; |
| @@ -15,7 +15,6 @@ | @@ -15,7 +15,6 @@ | ||
| 15 | :title="getMergeProps.title" | 15 | :title="getMergeProps.title" |
| 16 | @dblclick="handleTitleDbClick" | 16 | @dblclick="handleTitleDbClick" |
| 17 | /> | 17 | /> |
| 18 | - <slot name="titleSlot" v-if="!getMergeProps.title"></slot> | ||
| 19 | </template> | 18 | </template> |
| 20 | 19 | ||
| 21 | <template #footer v-if="!$slots.footer"> | 20 | <template #footer v-if="!$slots.footer"> |
| 1 | +import { formatToDateTime } from '/@/utils/dateUtil'; | ||
| 1 | import { FormSchema } from '/@/components/Form'; | 2 | import { FormSchema } from '/@/components/Form'; |
| 2 | import { BasicColumn } from '/@/components/Table'; | 3 | import { BasicColumn } from '/@/components/Table'; |
| 3 | import { DeviceTypeEnum } from '/@/api/device/model/deviceModel'; | 4 | import { DeviceTypeEnum } from '/@/api/device/model/deviceModel'; |
| 5 | +import {} from ''; | ||
| 4 | 6 | ||
| 5 | export const columns: BasicColumn[] = [ | 7 | export const columns: BasicColumn[] = [ |
| 6 | { | 8 | { |
| @@ -48,78 +50,183 @@ export const realTimeDataSearchSchemas: FormSchema[] = [ | @@ -48,78 +50,183 @@ export const realTimeDataSearchSchemas: FormSchema[] = [ | ||
| 48 | field: 'key', | 50 | field: 'key', |
| 49 | label: '键 / 值', | 51 | label: '键 / 值', |
| 50 | component: 'Input', | 52 | component: 'Input', |
| 51 | - colProps: { span: 12 }, | 53 | + colProps: { span: 8 }, |
| 52 | }, | 54 | }, |
| 53 | ]; | 55 | ]; |
| 54 | export const realTimeDataColumns: BasicColumn[] = [ | 56 | export const realTimeDataColumns: BasicColumn[] = [ |
| 55 | { | 57 | { |
| 56 | - title: '最后更新时间', | ||
| 57 | - dataIndex: 'update', | ||
| 58 | - width: 120, | ||
| 59 | - }, | ||
| 60 | - { | ||
| 61 | title: '键', | 58 | title: '键', |
| 62 | - dataIndex: 'label', | 59 | + dataIndex: 'key', |
| 63 | width: 100, | 60 | width: 100, |
| 64 | }, | 61 | }, |
| 65 | { | 62 | { |
| 66 | title: '值', | 63 | title: '值', |
| 67 | - dataIndex: 'name', | 64 | + dataIndex: 'value', |
| 68 | width: 160, | 65 | width: 160, |
| 69 | }, | 66 | }, |
| 67 | + { | ||
| 68 | + title: '最后更新时间', | ||
| 69 | + dataIndex: 'time', | ||
| 70 | + width: 120, | ||
| 71 | + format: (text) => formatToDateTime(text, 'YYYY-MM-DD HH:mm:ss'), | ||
| 72 | + }, | ||
| 70 | ]; | 73 | ]; |
| 71 | 74 | ||
| 72 | // 告警 | 75 | // 告警 |
| 73 | export const alarmSearchSchemas: FormSchema[] = [ | 76 | export const alarmSearchSchemas: FormSchema[] = [ |
| 74 | { | 77 | { |
| 75 | - field: 'icon', | 78 | + field: 'status', |
| 76 | label: '告警状态', | 79 | label: '告警状态', |
| 77 | component: 'Select', | 80 | component: 'Select', |
| 78 | colProps: { span: 6 }, | 81 | colProps: { span: 6 }, |
| 82 | + componentProps: { | ||
| 83 | + options: [ | ||
| 84 | + { | ||
| 85 | + label: '清除未确认', | ||
| 86 | + value: 'CLEARED_UNACK', | ||
| 87 | + }, | ||
| 88 | + { | ||
| 89 | + label: '激活未确认', | ||
| 90 | + value: 'ACTIVE_UNACK', | ||
| 91 | + }, | ||
| 92 | + { | ||
| 93 | + label: '清除已确认', | ||
| 94 | + value: 'CLEARED_ACK', | ||
| 95 | + }, | ||
| 96 | + { | ||
| 97 | + label: '激活已确认', | ||
| 98 | + value: 'ACTIVE_ACK', | ||
| 99 | + }, | ||
| 100 | + ], | ||
| 101 | + }, | ||
| 79 | }, | 102 | }, |
| 80 | { | 103 | { |
| 81 | - field: 'icon', | 104 | + field: 'type', |
| 82 | label: '告警类型', | 105 | label: '告警类型', |
| 83 | component: 'Input', | 106 | component: 'Input', |
| 84 | colProps: { span: 6 }, | 107 | colProps: { span: 6 }, |
| 85 | }, | 108 | }, |
| 86 | { | 109 | { |
| 87 | - field: 'icon', | 110 | + field: 'startTime', |
| 88 | label: ' ', | 111 | label: ' ', |
| 89 | component: 'DatePicker', | 112 | component: 'DatePicker', |
| 113 | + componentProps: { | ||
| 114 | + format: (value) => dayjs(value).valueOf(), | ||
| 115 | + }, | ||
| 90 | colProps: { span: 6 }, | 116 | colProps: { span: 6 }, |
| 91 | }, | 117 | }, |
| 92 | ]; | 118 | ]; |
| 93 | export const alarmColumns: BasicColumn[] = [ | 119 | export const alarmColumns: BasicColumn[] = [ |
| 94 | { | 120 | { |
| 95 | title: '告警时间', | 121 | title: '告警时间', |
| 96 | - dataIndex: 'aaa', | 122 | + dataIndex: 'createdTime', |
| 97 | width: 120, | 123 | width: 120, |
| 98 | }, | 124 | }, |
| 99 | { | 125 | { |
| 100 | title: '告警设备', | 126 | title: '告警设备', |
| 101 | - dataIndex: 'label', | 127 | + dataIndex: 'deviceName', |
| 102 | width: 100, | 128 | width: 100, |
| 103 | }, | 129 | }, |
| 104 | { | 130 | { |
| 105 | title: '类型', | 131 | title: '类型', |
| 106 | - dataIndex: 'ccc', | 132 | + dataIndex: 'type', |
| 107 | width: 160, | 133 | width: 160, |
| 108 | }, | 134 | }, |
| 109 | { | 135 | { |
| 110 | title: '告警级别', | 136 | title: '告警级别', |
| 111 | - dataIndex: 'ddd', | 137 | + dataIndex: 'severity', |
| 112 | width: 160, | 138 | width: 160, |
| 139 | + format: (text) => alarmLevel(text), | ||
| 113 | }, | 140 | }, |
| 114 | { | 141 | { |
| 115 | title: '状态', | 142 | title: '状态', |
| 116 | - dataIndex: 'eee', | 143 | + dataIndex: 'status', |
| 144 | + format: (text) => statusType(text), | ||
| 117 | width: 160, | 145 | width: 160, |
| 118 | }, | 146 | }, |
| 147 | +]; | ||
| 148 | +const alarmLevel = (type: string): string => { | ||
| 149 | + if (type === 'CRITICAL') { | ||
| 150 | + return '危险'; | ||
| 151 | + } else if (type === 'MAJOR') { | ||
| 152 | + return '重要'; | ||
| 153 | + } else if (type === 'MINOR') { | ||
| 154 | + return '次要'; | ||
| 155 | + } else if (type === 'WARNING') { | ||
| 156 | + return '警告'; | ||
| 157 | + } else { | ||
| 158 | + return '不确定'; | ||
| 159 | + } | ||
| 160 | +}; | ||
| 161 | +const statusType = (type: string): string => { | ||
| 162 | + if (type === 'CLEARED_UNACK') { | ||
| 163 | + return '清除未确认'; | ||
| 164 | + } else if (type === 'CLEARED_ACK') { | ||
| 165 | + return '清除已确认'; | ||
| 166 | + } else if (type === 'ACTIVE_ACK') { | ||
| 167 | + return '激活已确认'; | ||
| 168 | + } else { | ||
| 169 | + return '激活未确认'; | ||
| 170 | + } | ||
| 171 | +}; | ||
| 172 | + | ||
| 173 | +export const alarmSchemasForm: FormSchema[] = [ | ||
| 119 | { | 174 | { |
| 120 | - title: '操作', | ||
| 121 | - dataIndex: 'name', | ||
| 122 | - width: 160, | 175 | + field: 'deviceName', |
| 176 | + label: '告警设备', | ||
| 177 | + component: 'Input', | ||
| 178 | + componentProps: { | ||
| 179 | + disabled: true, | ||
| 180 | + }, | ||
| 181 | + }, | ||
| 182 | + | ||
| 183 | + { | ||
| 184 | + field: 'startTs', | ||
| 185 | + label: '开始时间', | ||
| 186 | + component: 'Input', | ||
| 187 | + componentProps: { | ||
| 188 | + disabled: true, | ||
| 189 | + }, | ||
| 190 | + }, | ||
| 191 | + { | ||
| 192 | + field: 'endTs', | ||
| 193 | + label: '结束时间', | ||
| 194 | + component: 'Input', | ||
| 195 | + componentProps: { | ||
| 196 | + disabled: true, | ||
| 197 | + }, | ||
| 198 | + }, | ||
| 199 | + { | ||
| 200 | + field: 'type', | ||
| 201 | + label: '告警类型', | ||
| 202 | + component: 'Input', | ||
| 203 | + componentProps: { | ||
| 204 | + disabled: true, | ||
| 205 | + }, | ||
| 206 | + }, | ||
| 207 | + { | ||
| 208 | + field: 'severity', | ||
| 209 | + label: '严重程度', | ||
| 210 | + component: 'Input', | ||
| 211 | + componentProps: { | ||
| 212 | + disabled: true, | ||
| 213 | + }, | ||
| 214 | + }, | ||
| 215 | + { | ||
| 216 | + field: 'status', | ||
| 217 | + label: '状态', | ||
| 218 | + component: 'Input', | ||
| 219 | + componentProps: { | ||
| 220 | + disabled: true, | ||
| 221 | + }, | ||
| 222 | + }, | ||
| 223 | + { | ||
| 224 | + field: 'details', | ||
| 225 | + label: '详情', | ||
| 226 | + component: 'InputTextArea', | ||
| 227 | + componentProps: { | ||
| 228 | + disabled: true, | ||
| 229 | + }, | ||
| 123 | }, | 230 | }, |
| 124 | ]; | 231 | ]; |
| 125 | 232 |
| 1 | +<template> | ||
| 2 | + <BasicModal | ||
| 3 | + v-bind="$attrs" | ||
| 4 | + title="告警详情" | ||
| 5 | + @register="registerModal" | ||
| 6 | + :canFullscreen="false" | ||
| 7 | + :footer="null" | ||
| 8 | + > | ||
| 9 | + <BasicForm @register="registerForm" /> | ||
| 10 | + <div class="flex justify-end"> | ||
| 11 | + <a-button type="primary" class="mr-4" @click="handleAlarm">处理</a-button> | ||
| 12 | + <a-button type="danger" @click="clearAlarm">清除</a-button> | ||
| 13 | + </div> | ||
| 14 | + </BasicModal> | ||
| 15 | +</template> | ||
| 16 | + | ||
| 17 | +<script lang="ts"> | ||
| 18 | + import { defineComponent, ref, unref } from 'vue'; | ||
| 19 | + import { BasicModal, useModalInner } from '/@/components/Modal'; | ||
| 20 | + import { BasicForm, useForm } from '/@/components/Form'; | ||
| 21 | + import { alarmSchemasForm } from '../../config/detail.config'; | ||
| 22 | + import { clearOrAckAlarm } from '/@/api/device/deviceManager'; | ||
| 23 | + export default defineComponent({ | ||
| 24 | + name: 'AlarmDetailDrawer', | ||
| 25 | + components: { | ||
| 26 | + BasicModal, | ||
| 27 | + BasicForm, | ||
| 28 | + }, | ||
| 29 | + setup() { | ||
| 30 | + const [registerForm, { setFieldsValue, resetFields }] = useForm({ | ||
| 31 | + showActionButtonGroup: false, | ||
| 32 | + schemas: alarmSchemasForm, | ||
| 33 | + }); | ||
| 34 | + const alarmId = ref(''); | ||
| 35 | + const [registerModal, { closeModal }] = useModalInner(async (data) => { | ||
| 36 | + await resetFields(); | ||
| 37 | + await setFieldsValue(data); | ||
| 38 | + alarmId.value = data.id; | ||
| 39 | + console.log(data); | ||
| 40 | + }); | ||
| 41 | + // 处理报警 | ||
| 42 | + const handleAlarm = async () => { | ||
| 43 | + await clearOrAckAlarm(unref(alarmId), false); | ||
| 44 | + closeModal(); | ||
| 45 | + }; | ||
| 46 | + // 清除报警 | ||
| 47 | + const clearAlarm = async () => { | ||
| 48 | + await clearOrAckAlarm(unref(alarmId), true); | ||
| 49 | + closeModal(); | ||
| 50 | + }; | ||
| 51 | + return { | ||
| 52 | + registerModal, | ||
| 53 | + registerForm, | ||
| 54 | + clearAlarm, | ||
| 55 | + handleAlarm, | ||
| 56 | + }; | ||
| 57 | + }, | ||
| 58 | + }); | ||
| 59 | +</script> | ||
| 60 | + | ||
| 61 | +<style lang="less" scoped></style> |
| @@ -6,15 +6,16 @@ | @@ -6,15 +6,16 @@ | ||
| 6 | :destroyOnClose="true" | 6 | :destroyOnClose="true" |
| 7 | @close="closeDrawer" | 7 | @close="closeDrawer" |
| 8 | :title="deviceDetail.name" | 8 | :title="deviceDetail.name" |
| 9 | + width="78%" | ||
| 9 | > | 10 | > |
| 10 | <Tabs v-model:activeKey="activeKey" :size="size" type="card"> | 11 | <Tabs v-model:activeKey="activeKey" :size="size" type="card"> |
| 11 | <TabPane key="1" tab="详情" | 12 | <TabPane key="1" tab="详情" |
| 12 | ><Detail ref="deviceDetailRef" :deviceDetail="deviceDetail" | 13 | ><Detail ref="deviceDetailRef" :deviceDetail="deviceDetail" |
| 13 | /></TabPane> | 14 | /></TabPane> |
| 14 | <TabPane key="2" tab="实时数据" v-if="deviceDetail?.deviceType !== 'GATEWAY'" | 15 | <TabPane key="2" tab="实时数据" v-if="deviceDetail?.deviceType !== 'GATEWAY'" |
| 15 | - ><RealTimeData | 16 | + ><RealTimeData :deviceDetail="deviceDetail" |
| 16 | /></TabPane> | 17 | /></TabPane> |
| 17 | - <TabPane key="3" tab="告警"><Alarm :id="tbDeviceId" /></TabPane> | 18 | + <TabPane key="3" tab="告警"><Alarm :id="deviceDetail.id" /></TabPane> |
| 18 | <TabPane key="4" tab="子设备" v-if="deviceDetail?.deviceType === 'GATEWAY'" | 19 | <TabPane key="4" tab="子设备" v-if="deviceDetail?.deviceType === 'GATEWAY'" |
| 19 | ><ChildDevice | 20 | ><ChildDevice |
| 20 | /></TabPane> | 21 | /></TabPane> |
| @@ -49,13 +50,12 @@ | @@ -49,13 +50,12 @@ | ||
| 49 | const size = ref('small'); | 50 | const size = ref('small'); |
| 50 | const deviceDetailRef = ref(); | 51 | const deviceDetailRef = ref(); |
| 51 | const deviceDetail: any = ref({}); | 52 | const deviceDetail: any = ref({}); |
| 52 | - const tbDeviceId = ref(''); | 53 | + |
| 53 | // 详情回显 | 54 | // 详情回显 |
| 54 | const [register] = useDrawerInner(async (data) => { | 55 | const [register] = useDrawerInner(async (data) => { |
| 55 | - const { id, tbDeviceId: tbId } = data; | 56 | + const { id } = data; |
| 56 | const res = await getDeviceDetail(id); | 57 | const res = await getDeviceDetail(id); |
| 57 | deviceDetail.value = res; | 58 | deviceDetail.value = res; |
| 58 | - tbDeviceId.value = tbId; | ||
| 59 | const { latitude, longitude, address } = res.deviceInfo; | 59 | const { latitude, longitude, address } = res.deviceInfo; |
| 60 | if (latitude) { | 60 | if (latitude) { |
| 61 | deviceDetailRef.value.initMap(longitude, latitude, address); | 61 | deviceDetailRef.value.initMap(longitude, latitude, address); |
| @@ -72,7 +72,6 @@ | @@ -72,7 +72,6 @@ | ||
| 72 | closeDrawer, | 72 | closeDrawer, |
| 73 | deviceDetail, | 73 | deviceDetail, |
| 74 | deviceDetailRef, | 74 | deviceDetailRef, |
| 75 | - tbDeviceId, | ||
| 76 | }; | 75 | }; |
| 77 | }, | 76 | }, |
| 78 | }); | 77 | }); |
| @@ -56,7 +56,7 @@ | @@ -56,7 +56,7 @@ | ||
| 56 | const DeviceStep1Ref = ref<InstanceType<typeof DeviceStep1>>(); | 56 | const DeviceStep1Ref = ref<InstanceType<typeof DeviceStep1>>(); |
| 57 | const DeviceStep2Ref = ref<InstanceType<typeof DeviceStep2>>(); | 57 | const DeviceStep2Ref = ref<InstanceType<typeof DeviceStep2>>(); |
| 58 | const { createMessage } = useMessage(); | 58 | const { createMessage } = useMessage(); |
| 59 | - const current = ref(1); | 59 | + const current = ref(0); |
| 60 | const isUpdate = ref<Boolean>(); | 60 | const isUpdate = ref<Boolean>(); |
| 61 | const deviceInfo = ref({}); | 61 | const deviceInfo = ref({}); |
| 62 | const getTitle = computed(() => (!unref(isUpdate) ? '新增设备' : '编辑设备')); | 62 | const getTitle = computed(() => (!unref(isUpdate) ? '新增设备' : '编辑设备')); |
| 1 | <template> | 1 | <template> |
| 2 | - <BasicTable @register="registerTable" /> | 2 | + <div> |
| 3 | + <BasicTable @register="registerTable"> | ||
| 4 | + <template #action="{ record }"> | ||
| 5 | + <TableAction | ||
| 6 | + :actions="[ | ||
| 7 | + { | ||
| 8 | + label: '详情', | ||
| 9 | + icon: 'ant-design:eye-outlined', | ||
| 10 | + onClick: handleDetail.bind(null, record), | ||
| 11 | + }, | ||
| 12 | + ]" | ||
| 13 | + /> | ||
| 14 | + </template> | ||
| 15 | + </BasicTable> | ||
| 16 | + <AlarmDetailModal @register="registerDetailModal" /> | ||
| 17 | + </div> | ||
| 3 | </template> | 18 | </template> |
| 4 | <script lang="ts"> | 19 | <script lang="ts"> |
| 5 | import { defineComponent } from 'vue'; | 20 | import { defineComponent } from 'vue'; |
| 6 | - import { BasicTable, useTable } from '/@/components/Table'; | 21 | + import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
| 7 | import { alarmColumns, alarmSearchSchemas } from '../../config/detail.config'; | 22 | import { alarmColumns, alarmSearchSchemas } from '../../config/detail.config'; |
| 8 | import { getDeviceAlarm } from '/@/api/device/deviceManager'; | 23 | import { getDeviceAlarm } from '/@/api/device/deviceManager'; |
| 24 | + import AlarmDetailModal from '../modal/AlarmDetailModal.vue'; | ||
| 25 | + import { useModal } from '/@/components/Modal'; | ||
| 9 | export default defineComponent({ | 26 | export default defineComponent({ |
| 10 | name: 'DeviceManagement', | 27 | name: 'DeviceManagement', |
| 11 | components: { | 28 | components: { |
| 12 | BasicTable, | 29 | BasicTable, |
| 30 | + TableAction, | ||
| 31 | + AlarmDetailModal, | ||
| 13 | }, | 32 | }, |
| 14 | props: { | 33 | props: { |
| 15 | id: { | 34 | id: { |
| @@ -26,15 +45,33 @@ | @@ -26,15 +45,33 @@ | ||
| 26 | schemas: alarmSearchSchemas, | 45 | schemas: alarmSearchSchemas, |
| 27 | }, | 46 | }, |
| 28 | useSearchForm: true, | 47 | useSearchForm: true, |
| 29 | - showTableSetting: true, | ||
| 30 | bordered: true, | 48 | bordered: true, |
| 31 | showIndexColumn: false, | 49 | showIndexColumn: false, |
| 32 | - beforeFetch: (data) => Reflect.set(data, 'deviceId', props.id), | 50 | + beforeFetch: (data) => { |
| 51 | + Reflect.set(data, 'deviceId', props.id); | ||
| 52 | + }, | ||
| 53 | + actionColumn: { | ||
| 54 | + width: 200, | ||
| 55 | + title: '操作', | ||
| 56 | + slots: { customRender: 'action' }, | ||
| 57 | + fixed: 'right', | ||
| 58 | + }, | ||
| 33 | }); | 59 | }); |
| 34 | - | 60 | + const [registerDetailModal, { openModal }] = useModal(); |
| 61 | + const handleDetail = (record: Recordable) => { | ||
| 62 | + openModal(true, record); | ||
| 63 | + }; | ||
| 35 | return { | 64 | return { |
| 36 | registerTable, | 65 | registerTable, |
| 66 | + registerDetailModal, | ||
| 67 | + handleDetail, | ||
| 37 | }; | 68 | }; |
| 38 | }, | 69 | }, |
| 39 | }); | 70 | }); |
| 40 | </script> | 71 | </script> |
| 72 | + | ||
| 73 | +<style> | ||
| 74 | + .aaa { | ||
| 75 | + position: absolute; | ||
| 76 | + } | ||
| 77 | +</style> |
| @@ -86,6 +86,7 @@ | @@ -86,6 +86,7 @@ | ||
| 86 | } | 86 | } |
| 87 | }; | 87 | }; |
| 88 | const copyDeviceToken = () => { | 88 | const copyDeviceToken = () => { |
| 89 | + // TODO:此处需要动态修改 | ||
| 89 | clipboardRef.value = props.deviceDetail.deviceToken; | 90 | clipboardRef.value = props.deviceDetail.deviceToken; |
| 90 | if (unref(clipboardRef)) { | 91 | if (unref(clipboardRef)) { |
| 91 | createMessage.success('复制成功~'); | 92 | createMessage.success('复制成功~'); |
| @@ -2,18 +2,42 @@ | @@ -2,18 +2,42 @@ | ||
| 2 | <BasicTable @register="registerTable" /> | 2 | <BasicTable @register="registerTable" /> |
| 3 | </template> | 3 | </template> |
| 4 | <script lang="ts"> | 4 | <script lang="ts"> |
| 5 | - import { defineComponent, reactive, onMounted, onUnmounted } from 'vue'; | 5 | + import { defineComponent, reactive } from 'vue'; |
| 6 | import { BasicTable, useTable } from '/@/components/Table'; | 6 | import { BasicTable, useTable } from '/@/components/Table'; |
| 7 | import { realTimeDataColumns, realTimeDataSearchSchemas } from '../../config/detail.config'; | 7 | import { realTimeDataColumns, realTimeDataSearchSchemas } from '../../config/detail.config'; |
| 8 | import { useWebSocket } from '@vueuse/core'; | 8 | import { useWebSocket } from '@vueuse/core'; |
| 9 | import { JWT_TOKEN_KEY } from '/@/enums/cacheEnum'; | 9 | import { JWT_TOKEN_KEY } from '/@/enums/cacheEnum'; |
| 10 | import { getAuthCache } from '/@/utils/auth'; | 10 | import { getAuthCache } from '/@/utils/auth'; |
| 11 | + import type { socketDataType } from '../../types'; | ||
| 12 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
| 11 | export default defineComponent({ | 13 | export default defineComponent({ |
| 12 | - name: 'DeviceManagement', | 14 | + name: 'RealTimeData', |
| 13 | components: { | 15 | components: { |
| 14 | BasicTable, | 16 | BasicTable, |
| 15 | }, | 17 | }, |
| 16 | - setup(_) { | 18 | + props: { |
| 19 | + deviceDetail: { | ||
| 20 | + type: Object, | ||
| 21 | + required: true, | ||
| 22 | + }, | ||
| 23 | + }, | ||
| 24 | + setup(props) { | ||
| 25 | + const token = getAuthCache(JWT_TOKEN_KEY); | ||
| 26 | + const state = reactive({ | ||
| 27 | + server: `ws://101.133.234.90:8080/api/ws/plugins/telemetry?token=${token}`, | ||
| 28 | + sendValue: JSON.stringify({ | ||
| 29 | + tsSubCmds: [ | ||
| 30 | + { | ||
| 31 | + entityType: 'DEVICE', | ||
| 32 | + entityId: props.deviceDetail.tbDeviceId, | ||
| 33 | + scope: 'LATEST_TELEMETRY', | ||
| 34 | + cmdId: 1, | ||
| 35 | + }, | ||
| 36 | + ], | ||
| 37 | + }), | ||
| 38 | + recordList: Array<socketDataType>(), | ||
| 39 | + }); | ||
| 40 | + const { createMessage } = useMessage(); | ||
| 17 | const [registerTable] = useTable({ | 41 | const [registerTable] = useTable({ |
| 18 | columns: realTimeDataColumns, | 42 | columns: realTimeDataColumns, |
| 19 | formConfig: { | 43 | formConfig: { |
| @@ -21,48 +45,52 @@ | @@ -21,48 +45,52 @@ | ||
| 21 | schemas: realTimeDataSearchSchemas, | 45 | schemas: realTimeDataSearchSchemas, |
| 22 | }, | 46 | }, |
| 23 | useSearchForm: true, | 47 | useSearchForm: true, |
| 24 | - showTableSetting: true, | 48 | + showTableSetting: false, |
| 25 | bordered: true, | 49 | bordered: true, |
| 26 | showIndexColumn: false, | 50 | showIndexColumn: false, |
| 51 | + dataSource: state.recordList, | ||
| 27 | }); | 52 | }); |
| 28 | - const token = getAuthCache(JWT_TOKEN_KEY); | ||
| 29 | 53 | ||
| 30 | - const state = reactive({ | ||
| 31 | - server: `ws://192.168.10.139:8080/api/ws/plugins/telemetry?token=${token}`, | ||
| 32 | - sendValue: '', | ||
| 33 | - recordList: [] as { id: number; time: number; res: string }[], | ||
| 34 | - }); | ||
| 35 | - const { status, data, send, close, open } = useWebSocket(state.server, { | ||
| 36 | - autoReconnect: false, | ||
| 37 | - heartbeat: true, | ||
| 38 | - }); | ||
| 39 | - onMounted(() => { | ||
| 40 | - open(); | ||
| 41 | - send( | ||
| 42 | - JSON.stringify({ | ||
| 43 | - attrSubCmds: [], | ||
| 44 | - tsSubCmds: [ | ||
| 45 | - { | ||
| 46 | - entityType: 'DEVICE', | ||
| 47 | - entityId: '3199a500-6302-11ec-ba36-417bcc842c0a', | ||
| 48 | - scope: 'LATEST_TELEMETRY', | ||
| 49 | - cmdId: 1, | ||
| 50 | - }, | ||
| 51 | - ], | ||
| 52 | - historyCmds: [], | ||
| 53 | - entityDataCmds: [], | ||
| 54 | - entityDataUnsubscribeCmds: [], | ||
| 55 | - alarmDataCmds: [], | ||
| 56 | - alarmDataUnsubscribeCmds: [], | ||
| 57 | - entityCountCmds: [], | ||
| 58 | - entityCountUnsubscribeCmds: [], | ||
| 59 | - }) | ||
| 60 | - ); | ||
| 61 | - | ||
| 62 | - console.log(JSON.parse(data.value)); | ||
| 63 | - }); | ||
| 64 | - onUnmounted(() => { | ||
| 65 | - close(); | 54 | + const { send } = useWebSocket(state.server, { |
| 55 | + onConnected() { | ||
| 56 | + send(state.sendValue); | ||
| 57 | + }, | ||
| 58 | + onMessage(_, e) { | ||
| 59 | + const { data } = JSON.parse(e.data); | ||
| 60 | + console.log('来新消息了'); | ||
| 61 | + const newArray: any = []; | ||
| 62 | + for (const key in data) { | ||
| 63 | + const newData = data[key].flat(1); | ||
| 64 | + let obj = { | ||
| 65 | + key, | ||
| 66 | + time: newData[0], | ||
| 67 | + value: newData[1], | ||
| 68 | + }; | ||
| 69 | + if (state.recordList.length === 0) { | ||
| 70 | + state.recordList.push(obj); | ||
| 71 | + } else { | ||
| 72 | + newArray.push(obj); | ||
| 73 | + } | ||
| 74 | + } | ||
| 75 | + newArray.forEach((item) => { | ||
| 76 | + let flag = false; | ||
| 77 | + state.recordList.forEach((item1) => { | ||
| 78 | + if (item.key === item1.key) { | ||
| 79 | + item1.time = item.time; | ||
| 80 | + item1.value = item.value; | ||
| 81 | + console.log('哈哈哈', item, item1, state.recordList); | ||
| 82 | + flag = true; | ||
| 83 | + } | ||
| 84 | + }); | ||
| 85 | + if (!flag) { | ||
| 86 | + state.recordList.unshift(item); | ||
| 87 | + } | ||
| 88 | + }); | ||
| 89 | + }, | ||
| 90 | + onDisconnected() {}, | ||
| 91 | + onError() { | ||
| 92 | + createMessage.error('webSocket连接超时,请联系管理员'); | ||
| 93 | + }, | ||
| 66 | }); | 94 | }); |
| 67 | 95 | ||
| 68 | return { | 96 | return { |
| @@ -18,3 +18,9 @@ export interface DeviceType { | @@ -18,3 +18,9 @@ export interface DeviceType { | ||
| 18 | tenantCode: string; | 18 | tenantCode: string; |
| 19 | updateTime: string; | 19 | updateTime: string; |
| 20 | } | 20 | } |
| 21 | + | ||
| 22 | +export interface socketDataType { | ||
| 23 | + key: string; | ||
| 24 | + value: string; | ||
| 25 | + time: number; | ||
| 26 | +} |