Commit c8dcf096c768a552b826af6595304722520b12b6
Committed by
gesilong
1 parent
1dd4c89f
feat: 设备-详情-三个设备类型(燃气、水表、电表)增加上报功能
Showing
4 changed files
with
116 additions
and
10 deletions
| @@ -6,12 +6,12 @@ VITE_GLOB_PUBLIC_PATH = / | @@ -6,12 +6,12 @@ VITE_GLOB_PUBLIC_PATH = / | ||
| 6 | 6 | ||
| 7 | # Cross-domain proxy, you can configure multiple | 7 | # Cross-domain proxy, you can configure multiple |
| 8 | # Please note that no line breaks | 8 | # Please note that no line breaks |
| 9 | - | 9 | +# https://iot.hzzlyun.com 线上生产地址 |
| 10 | # 本地 | 10 | # 本地 |
| 11 | -VITE_PROXY = [["/api","http://localhost:8080/api"],["/thingskit-scada","http://localhost:5173/thingskit-scada"],["/large-designer", "http://localhost:5555/large-designer/"]] | 11 | +VITE_PROXY = [["/api","https://iot.hzzlyun.com/api"],["/thingskit-scada","http://localhost:5173/thingskit-scada"],["/large-designer", "http://localhost:5555/large-designer/"]] |
| 12 | 12 | ||
| 13 | # 实时数据的ws地址 | 13 | # 实时数据的ws地址 |
| 14 | -VITE_GLOB_WEB_SOCKET = ws://localhost:8080/api/ws/plugins/telemetry?token= | 14 | +VITE_GLOB_WEB_SOCKET = wss://iot.hzzlyun.com/api/ws/plugins/telemetry?token= |
| 15 | 15 | ||
| 16 | # Delete console | 16 | # Delete console |
| 17 | VITE_GLOB_DROP_CONSOLE = true | 17 | VITE_GLOB_DROP_CONSOLE = true |
| @@ -28,5 +28,6 @@ export default { | @@ -28,5 +28,6 @@ export default { | ||
| 28 | historyTrendText: 'History trend', | 28 | historyTrendText: 'History trend', |
| 29 | commandDeliveryText: 'Command delivery', | 29 | commandDeliveryText: 'Command delivery', |
| 30 | serviceText: 'Service', | 30 | serviceText: 'Service', |
| 31 | + reportText: 'Report', | ||
| 31 | dateRangeText: 'Date range', | 32 | dateRangeText: 'Date range', |
| 32 | }; | 33 | }; |
| @@ -30,6 +30,7 @@ export default { | @@ -30,6 +30,7 @@ export default { | ||
| 30 | historyTrendText: '历史趋势', | 30 | historyTrendText: '历史趋势', |
| 31 | commandDeliveryText: '命令下发', | 31 | commandDeliveryText: '命令下发', |
| 32 | serviceText: '服务', | 32 | serviceText: '服务', |
| 33 | + reportText: '上报', | ||
| 33 | dateRangeText: '时间范围', | 34 | dateRangeText: '时间范围', |
| 34 | directorName: '负责人', | 35 | directorName: '负责人', |
| 35 | }; | 36 | }; |
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | import { nextTick, onMounted, onUnmounted, reactive, ref, unref, computed } from 'vue'; | 2 | import { nextTick, onMounted, onUnmounted, reactive, ref, unref, computed } from 'vue'; |
| 3 | - import { List, Card, Tooltip, Space, PaginationProps } from 'ant-design-vue'; | 3 | + import { List, Card, Tooltip, Space, PaginationProps, InputNumber } from 'ant-design-vue'; |
| 4 | import { PageWrapper } from '/@/components/Page'; | 4 | import { PageWrapper } from '/@/components/Page'; |
| 5 | import { BasicTable, useTable } from '/@/components/Table'; | 5 | import { BasicTable, useTable } from '/@/components/Table'; |
| 6 | import { realTimeDataColumns } from '../../config/detail.config'; | 6 | import { realTimeDataColumns } from '../../config/detail.config'; |
| @@ -12,7 +12,7 @@ | @@ -12,7 +12,7 @@ | ||
| 12 | import { BasicForm, useForm } from '/@/components/Form'; | 12 | import { BasicForm, useForm } from '/@/components/Form'; |
| 13 | import HistoryData from './HistoryData.vue'; | 13 | import HistoryData from './HistoryData.vue'; |
| 14 | import { BasicModal, useModal } from '/@/components/Modal'; | 14 | import { BasicModal, useModal } from '/@/components/Modal'; |
| 15 | - import { getDeviceAttrs } from '/@/api/device/deviceManager'; | 15 | + import { getDeviceAttrs, getDeviceToken } from '/@/api/device/deviceManager'; |
| 16 | import { DeviceRecord } from '/@/api/device/model/deviceModel'; | 16 | import { DeviceRecord } from '/@/api/device/model/deviceModel'; |
| 17 | import { isArray, isNull, isNullOrUnDef, isObject } from '/@/utils/is'; | 17 | import { isArray, isNull, isNullOrUnDef, isObject } from '/@/utils/is'; |
| 18 | import { useGlobSetting } from '/@/hooks/setting'; | 18 | import { useGlobSetting } from '/@/hooks/setting'; |
| @@ -37,6 +37,8 @@ | @@ -37,6 +37,8 @@ | ||
| 37 | } from './ModelOfMatter.config'; | 37 | } from './ModelOfMatter.config'; |
| 38 | import { useJsonParse } from '/@/hooks/business/useJsonParse'; | 38 | import { useJsonParse } from '/@/hooks/business/useJsonParse'; |
| 39 | import { useI18n } from '/@/hooks/web/useI18n'; | 39 | import { useI18n } from '/@/hooks/web/useI18n'; |
| 40 | + import { defHttp } from '/@/utils/http/axios'; | ||
| 41 | + | ||
| 40 | 42 | ||
| 41 | interface ReceiveMessage { | 43 | interface ReceiveMessage { |
| 42 | data: { | 44 | data: { |
| @@ -46,6 +48,41 @@ | @@ -46,6 +48,41 @@ | ||
| 46 | 48 | ||
| 47 | const { t } = useI18n(); | 49 | const { t } = useI18n(); |
| 48 | 50 | ||
| 51 | + const reportDeviceKeyMap = { | ||
| 52 | + GC: '燃气设备', | ||
| 53 | + WU: '水表设备', | ||
| 54 | + EC: '电表设备', | ||
| 55 | + } as const; | ||
| 56 | + | ||
| 57 | + const reportDeviceKeys = Object.keys(reportDeviceKeyMap); | ||
| 58 | + | ||
| 59 | + type ReportDeviceKey = keyof typeof reportDeviceKeyMap; | ||
| 60 | + | ||
| 61 | + const reportFormModel = reactive<Record<ReportDeviceKey, number | undefined>>({ | ||
| 62 | + GC: undefined, | ||
| 63 | + WU: undefined, | ||
| 64 | + EC: undefined, | ||
| 65 | + }); | ||
| 66 | + | ||
| 67 | + const currentReportKey = ref<ReportDeviceKey | ''>(''); | ||
| 68 | + | ||
| 69 | + const currentReportLabel = computed(() => { | ||
| 70 | + const key = unref(currentReportKey); | ||
| 71 | + return key ? reportDeviceKeyMap[key] : ''; | ||
| 72 | + }); | ||
| 73 | + | ||
| 74 | + const currentReportValue = computed<number | undefined>({ | ||
| 75 | + get() { | ||
| 76 | + const key = unref(currentReportKey); | ||
| 77 | + return key ? reportFormModel[key] : undefined; | ||
| 78 | + }, | ||
| 79 | + set(value) { | ||
| 80 | + const key = unref(currentReportKey); | ||
| 81 | + if (!key) return; | ||
| 82 | + reportFormModel[key] = value; | ||
| 83 | + }, | ||
| 84 | + }); | ||
| 85 | + | ||
| 49 | const props = defineProps<{ | 86 | const props = defineProps<{ |
| 50 | deviceDetail: DeviceRecord; | 87 | deviceDetail: DeviceRecord; |
| 51 | }>(); | 88 | }>(); |
| @@ -197,6 +234,8 @@ | @@ -197,6 +234,8 @@ | ||
| 197 | } | 234 | } |
| 198 | 235 | ||
| 199 | const [registerModal, { openModal }] = useModal(); | 236 | const [registerModal, { openModal }] = useModal(); |
| 237 | + const [registerReportModal, { openModal: openReportModal, closeModal: closeReportModal }] = | ||
| 238 | + useModal(); | ||
| 200 | 239 | ||
| 201 | const mode = ref<EnumTableCardMode>(EnumTableCardMode.CARD); | 240 | const mode = ref<EnumTableCardMode>(EnumTableCardMode.CARD); |
| 202 | 241 | ||
| @@ -291,6 +330,40 @@ | @@ -291,6 +330,40 @@ | ||
| 291 | openModal(true); | 330 | openModal(true); |
| 292 | }; | 331 | }; |
| 293 | 332 | ||
| 333 | + const handleReport = (record: SocketInfoDataSourceItemType) => { | ||
| 334 | + const { key } = record; | ||
| 335 | + if (!reportDeviceKeys.includes(key)) return; | ||
| 336 | + currentReportKey.value = key as ReportDeviceKey; | ||
| 337 | + openReportModal(true); | ||
| 338 | + }; | ||
| 339 | + | ||
| 340 | + const handleReportSave = async () => { | ||
| 341 | + const key = unref(currentReportKey); | ||
| 342 | + if (!key) return; | ||
| 343 | + const token = await getDeviceToken(props.deviceDetail.tbDeviceId); | ||
| 344 | + console.log('token.credentialsId', token.credentialsId); | ||
| 345 | + console.log('handleReportSave', { key, value: reportFormModel[key] }); | ||
| 346 | + // https://iot.hzzlyun.com/api/v1/HPlEWlrVPNlAbZ6WQpn2/telemetry | ||
| 347 | + // 入参 | ||
| 348 | + const data = { [key]: reportFormModel[key] }; | ||
| 349 | + const credentialsId = token.credentialsId; | ||
| 350 | + // 写一个接口请求,固定链接,不依赖token https://iot.hzzlyun.com/api/v1/${credentialsId}/telemetry | ||
| 351 | + await defHttp.post( | ||
| 352 | + { | ||
| 353 | + url: `https://iot.hzzlyun.com/api/v1/${credentialsId}/telemetry`, | ||
| 354 | + data, | ||
| 355 | + }, | ||
| 356 | + { | ||
| 357 | + joinPrefix: false, | ||
| 358 | + apiUrl: '', | ||
| 359 | + withToken: false, | ||
| 360 | + } | ||
| 361 | + ); | ||
| 362 | + | ||
| 363 | + createMessage.success('保存成功'); | ||
| 364 | + closeReportModal(); | ||
| 365 | + }; | ||
| 366 | + | ||
| 294 | const getIsModbusDevice = computed( | 367 | const getIsModbusDevice = computed( |
| 295 | () => | 368 | () => |
| 296 | props.deviceDetail.transportType === TransportTypeEnum.TCP && | 369 | props.deviceDetail.transportType === TransportTypeEnum.TCP && |
| @@ -307,21 +380,21 @@ | @@ -307,21 +380,21 @@ | ||
| 307 | open(); | 380 | open(); |
| 308 | }); | 381 | }); |
| 309 | 382 | ||
| 310 | - const formatValue = (item: SocketInfoDataSourceItemType) => { | 383 | + const formatValue = (item: SocketInfoDataSourceItemType): string => { |
| 311 | if (isNullOrUnDef(item) || isNullOrUnDef(item.value)) return '--'; | 384 | if (isNullOrUnDef(item) || isNullOrUnDef(item.value)) return '--'; |
| 312 | 385 | ||
| 313 | if (unref(getIsModbusDevice) && item.type === DataTypeEnum.BOOL) { | 386 | if (unref(getIsModbusDevice) && item.type === DataTypeEnum.BOOL) { |
| 314 | const _result = Reflect.get(item.enum || {}, item.value as string); | 387 | const _result = Reflect.get(item.enum || {}, item.value as string); |
| 315 | - return isNullOrUnDef(_result) ? item.value : _result; | 388 | + return isNullOrUnDef(_result) ? String(item.value) : String(_result); |
| 316 | } | 389 | } |
| 317 | 390 | ||
| 318 | switch (item.type) { | 391 | switch (item.type) { |
| 319 | case DataTypeEnum.BOOL: | 392 | case DataTypeEnum.BOOL: |
| 320 | - return !!Number(item.value) ? item.boolOpen! : item.boolClose!; | 393 | + return !!Number(item.value) ? (item.boolOpen ?? '--') : (item.boolClose ?? '--'); |
| 321 | case DataTypeEnum.ENUM: | 394 | case DataTypeEnum.ENUM: |
| 322 | - return item.enum?.[item.value as string]; | 395 | + return item.enum?.[item.value as string] ?? '--'; |
| 323 | default: | 396 | default: |
| 324 | - return item.value || '--'; | 397 | + return String(item.value ?? '--'); |
| 325 | } | 398 | } |
| 326 | }; | 399 | }; |
| 327 | 400 | ||
| @@ -429,6 +502,22 @@ | @@ -429,6 +502,22 @@ | ||
| 429 | @click="handleShowDetail(item)" | 502 | @click="handleShowDetail(item)" |
| 430 | /> | 503 | /> |
| 431 | </Tooltip> | 504 | </Tooltip> |
| 505 | + <!-- 上报按钮 显示判断 --> | ||
| 506 | + <!-- 燃气设备 GC--> | ||
| 507 | + <!-- 水表设备 WU--> | ||
| 508 | + <!-- 电表设备 EC--> | ||
| 509 | + <Tooltip :title="t('business.reportText')" | ||
| 510 | + v-if="reportDeviceKeys.includes(item.key)" | ||
| 511 | + > | ||
| 512 | + <SvgIcon | ||
| 513 | + name="shuiwen" | ||
| 514 | + prefix="iconfont" | ||
| 515 | + class="cursor-pointer text-lg text-blue-500" | ||
| 516 | + @click="handleReport(item)" | ||
| 517 | + /> | ||
| 518 | + </Tooltip> | ||
| 519 | + | ||
| 520 | + | ||
| 432 | </Space> | 521 | </Space> |
| 433 | </template> | 522 | </template> |
| 434 | <section class="min-h-16 flex flex-col justify-between"> | 523 | <section class="min-h-16 flex flex-col justify-between"> |
| @@ -513,6 +602,21 @@ | @@ -513,6 +602,21 @@ | ||
| 513 | > | 602 | > |
| 514 | <HistoryData :deviceDetail="props.deviceDetail" :attr="socketInfo.attr" /> | 603 | <HistoryData :deviceDetail="props.deviceDetail" :attr="socketInfo.attr" /> |
| 515 | </BasicModal> | 604 | </BasicModal> |
| 605 | + <BasicModal | ||
| 606 | + @register="registerReportModal" | ||
| 607 | + :title="`${t('business.reportText')}`" | ||
| 608 | + width="40%" | ||
| 609 | + :minHeight="0" | ||
| 610 | + :bodyStyle="{ padding: '12px 16px' }" | ||
| 611 | + destroy-on-close | ||
| 612 | + okText="提交" | ||
| 613 | + @ok="handleReportSave" | ||
| 614 | + > | ||
| 615 | + <div class="p-1 flex items-center gap-2"> | ||
| 616 | + <div class="w-20 text-right whitespace-nowrap">{{ currentReportLabel }}</div> | ||
| 617 | + <InputNumber v-model:value="currentReportValue" class="flex-1 w-full" size="small" /> | ||
| 618 | + </div> | ||
| 619 | + </BasicModal> | ||
| 516 | <ObjectModelCommandDeliveryModal | 620 | <ObjectModelCommandDeliveryModal |
| 517 | @register="register" | 621 | @register="register" |
| 518 | :deviceId="deviceDetail.tbDeviceId" | 622 | :deviceId="deviceDetail.tbDeviceId" |