Przeglądaj źródła

feat(views): 实时监测页面点击设备时,支持显示和修改数据

wangcong 3 tygodni temu
rodzic
commit
73c3aabe76

+ 33 - 0
src/api/index.ts

@@ -55,6 +55,7 @@ import type {
   GetListItem,
   GroupingList,
   GroupingListData,
+  GroupModuleDevData,
   GroupModuleInfo,
   GroupModuleQuery,
   GroupRegions,
@@ -1030,3 +1031,35 @@ export const updateGroupModuleInfo = async (params: Partial<GroupModuleInfo>) =>
     body: JSON.stringify(params),
   });
 };
+
+export const getGroupModuleDevData = async (deviceId: number, deviceType: number) => {
+  const data = await request<GroupModuleDevData>(apiBiz('/moduleInfo/info/device/detail'), {
+    method: 'POST',
+    body: JSON.stringify({
+      deviceId,
+      deviceType,
+    }),
+  });
+
+  return data;
+};
+
+export const updateGroupModuleDevData = async (deviceId: number, deviceParamCode: string, value: number | string) => {
+  await request(apiBiz('/moduleInfo/update/status'), {
+    method: 'POST',
+    body: JSON.stringify({
+      deviceId,
+      deviceParamCode,
+      value,
+    }),
+  });
+};
+
+export const getGroupModuleDevStatus = async (groupId: number) => {
+  await request(apiBiz('/moduleInfo/info/batch/status'), {
+    method: 'POST',
+    body: JSON.stringify({
+      groupId,
+    }),
+  });
+};

+ 9 - 0
src/types/index.ts

@@ -2158,6 +2158,15 @@ export interface GroupModuleInfo {
   deviceIds: string;
 }
 
+export interface GroupModuleDevData {
+  deviceId: number;
+  deviceName: string;
+  dataList: {
+    dataCode: string;
+    value?: number | string;
+  }[];
+}
+
 export interface UploadLogo {
   etag: string;
   versionId: string;

+ 218 - 47
src/views/real-time-monitor/DeviceCtrlModal.vue

@@ -1,37 +1,57 @@
 <script setup lang="ts">
-import { computed } from 'vue';
+import { computed, ref, watch } from 'vue';
+import { Modal } from 'ant-design-vue';
 
 import SvgIcon from '@/components/SvgIcon.vue';
+import { useRequest } from '@/hooks/request';
 import { useViewVisible } from '@/hooks/view-visible';
 import { t } from '@/i18n';
+import { getGroupModuleDevData, updateGroupModuleDevData } from '@/api';
+import { waitTime } from '@/utils';
+import { DevParamChillerUnit, DevParamCoolingPump, DevParamCoolingTower } from '@/constants/device-params';
 
-import type { DeviceType } from '../device-work-status/device-card';
+import { DeviceType } from '../device-work-status/device-card';
+
+import type { EquipmentDetailsItem } from '@/types';
 
 interface Props {
-  title?: string;
-  deviceType?: DeviceType;
+  info?: EquipmentDetailsItem;
 }
 
-defineProps<Props>();
+const props = defineProps<Props>();
 
 defineEmits<{
   openDevBatchExe: [];
 }>();
 
 const { visible, showView, hideView } = useViewVisible();
+const { isLoading, handleRequest } = useRequest();
+const deviceRealTimeData = ref<Record<string, number | string | undefined>>({});
+
+const deviceType = computed(() => {
+  return props.info?.deviceQueryVo.deviceType;
+});
 
 const disableStartStopCtrl = computed(() => {
-  return true;
+  const { isLocale, isAuto, isDisable } = getDeviceStatus();
+  return isLocale || isAuto || isDisable;
 });
 
 const startStopTip = computed(() => {
+  const { isLocale, isAuto, isDisable } = getDeviceStatus();
   const tips: string[] = [];
 
-  tips.push(
-    t('realTimeMonitor.startStopControlTipLocal'),
-    t('realTimeMonitor.startStopControlTipAuto'),
-    t('realTimeMonitor.startStopControlTipDisable'),
-  );
+  if (isLocale) {
+    tips.push(t('realTimeMonitor.startStopControlTipLocal'));
+  }
+
+  if (isAuto) {
+    tips.push(t('realTimeMonitor.startStopControlTipAuto'));
+  }
+
+  if (isDisable) {
+    tips.push(t('realTimeMonitor.startStopControlTipDisable'));
+  }
 
   let tipText = '';
 
@@ -42,6 +62,110 @@ const startStopTip = computed(() => {
   return tipText;
 });
 
+const getDeviceStatus = () => {
+  const { localRemoteStatus, manualAutoStatus, disableEnableStatus } = deviceRealTimeData.value;
+
+  return {
+    isLocale: localRemoteStatus === '本地',
+    isAuto: manualAutoStatus === 1,
+    isDisable: disableEnableStatus === 0,
+  };
+};
+
+watch(visible, () => {
+  if (visible.value) {
+    getDeviceData();
+  } else {
+    deviceRealTimeData.value = {};
+  }
+});
+
+const getDeviceData = () => {
+  handleRequest(async () => {
+    if (!props.info?.deviceQueryVo) {
+      return;
+    }
+
+    const { id, deviceType } = props.info.deviceQueryVo;
+    const data = await getGroupModuleDevData(id, deviceType);
+
+    data.dataList.forEach((item) => {
+      deviceRealTimeData.value[item.dataCode] = item.value;
+    });
+  });
+};
+
+const updateDeviceData = (paramCode: string, value?: string | number | null) => {
+  handleRequest(async () => {
+    if (!props.info?.deviceQueryVo) {
+      return;
+    }
+
+    const { id } = props.info.deviceQueryVo;
+
+    try {
+      if (value !== undefined && value !== null) {
+        await updateGroupModuleDevData(id, paramCode, value);
+      }
+      // eslint-disable-next-line no-useless-catch
+    } catch (err) {
+      throw err;
+    } finally {
+      await waitTime();
+      getDeviceData();
+    }
+  });
+};
+
+const handleDisableEnableSwitch = () => {
+  const { disableEnableStatus } = deviceRealTimeData.value;
+  const title = disableEnableStatus ? t('common.disable') : t('common.enable');
+  const value = disableEnableStatus ? 0 : 1;
+
+  Modal.confirm({
+    title: t('realTimeMonitor.confirmSwitchToMode', { mode: title }),
+    closable: true,
+    centered: true,
+    onOk() {
+      updateDeviceData('disableEnableStatus', value);
+    },
+  });
+};
+
+const handleAutoManualSwitch = () => {
+  const { manualAutoStatus } = deviceRealTimeData.value;
+  const title = manualAutoStatus ? t('common.manual') : t('common.automatic');
+  const content = manualAutoStatus
+    ? t('realTimeMonitor.confirmSwitchToManualTip')
+    : t('realTimeMonitor.confirmSwitchToAutoTip');
+  const value = manualAutoStatus ? 0 : 1;
+
+  Modal.confirm({
+    title: t('realTimeMonitor.confirmSwitchToMode', { mode: title }),
+    content,
+    closable: true,
+    centered: true,
+    onOk() {
+      updateDeviceData('manualAutoStatus', value);
+    },
+  });
+};
+
+const handleStartStopSwitch = () => {
+  const { startStopOrder } = deviceRealTimeData.value;
+  const title = startStopOrder ? t('common.confirmClose') : t('common.confirmOpen');
+  const value = startStopOrder ? 0 : 1;
+
+  Modal.confirm({
+    title: title + props.info?.deviceQueryVo.deviceName,
+    closable: true,
+    centered: true,
+    onOk() {
+      updateDeviceData('startStopOrder', value);
+    },
+  });
+};
+
 defineExpose({
   showView,
   hideView,
@@ -59,37 +183,55 @@ defineExpose({
   >
     <template #title>
       <div class="dev-ctrl-modal-header">
-        <span>{{ '三期-1#冷水主机' }}</span>
+        <span>{{ info?.deviceQueryVo.deviceName }}</span>
         <span class="dev-ctrl-modal-operate">
           {{ $t('common.viewMore') }}
           <SvgIcon name="right" />
         </span>
       </div>
     </template>
-    <div class="dev-ctrl-modal-item">
-      <span>{{ $t('realTimeMonitor.chilledWaterOutletTemperature') }}</span>
-      <span>{{ '11.6' }}℃</span>
-    </div>
-    <div class="dev-ctrl-modal-item">
-      <span>{{ $t('realTimeMonitor.loadRate') }}</span>
-      <span>{{ '70.3' }}%</span>
-    </div>
-    <div class="dev-ctrl-modal-item">
-      <span>{{ $t('realTimeMonitor.activePower') }}</span>
-      <span>{{ '102' }}kw</span>
-    </div>
-    <div class="dev-ctrl-modal-item">
-      <span>{{ $t('realTimeMonitor.localRemoteStatus') }}</span>
-      <span>{{ '远程' }}</span>
-    </div>
-    <div class="dev-ctrl-modal-item">
-      <span>{{ $t('realTimeMonitor.activePower') }}</span>
-      <span>{{ '10.99' }}kw</span>
-    </div>
-    <div class="dev-ctrl-modal-item">
-      <span>{{ $t('realTimeMonitor.runningTime') }}</span>
-      <span>{{ '100009.92' }}{{ $t('common.hour') }}</span>
-    </div>
+    <template v-if="deviceType === DeviceType.冷水主机">
+      <div class="dev-ctrl-modal-item">
+        <span>{{ $t('realTimeMonitor.chilledWaterOutletTemperature') }}</span>
+        <span>{{ deviceRealTimeData[DevParamChillerUnit.冷冻水出水温度] ?? '-' }}℃</span>
+      </div>
+      <div class="dev-ctrl-modal-item">
+        <span>{{ $t('realTimeMonitor.loadRate') }}</span>
+        <span>{{ deviceRealTimeData[DevParamChillerUnit.负载率] ?? '-' }}%</span>
+      </div>
+      <div class="dev-ctrl-modal-item">
+        <span>{{ $t('realTimeMonitor.activePower') }}</span>
+        <span>{{ deviceRealTimeData[DevParamChillerUnit.有功功率] ?? '-' }}kw</span>
+      </div>
+    </template>
+    <template v-if="deviceType === DeviceType.冷却塔">
+      <div class="dev-ctrl-modal-item">
+        <span>{{ $t('realTimeMonitor.localRemoteStatus') }}</span>
+        <span>{{ deviceRealTimeData[DevParamCoolingTower.本地远程状态] ?? '-' }}</span>
+      </div>
+      <div class="dev-ctrl-modal-item">
+        <span>{{ $t('realTimeMonitor.activePower') }}</span>
+        <span>{{ deviceRealTimeData[DevParamCoolingTower.有功功率] ?? '-' }}kw</span>
+      </div>
+      <div class="dev-ctrl-modal-item">
+        <span>{{ $t('realTimeMonitor.runningTime') }}</span>
+        <span>{{ deviceRealTimeData[DevParamCoolingTower.运行时间] ?? '-' }}{{ $t('common.hour') }}</span>
+      </div>
+    </template>
+    <template v-if="deviceType === DeviceType.冷冻泵 || deviceType === DeviceType.冷却泵">
+      <div class="dev-ctrl-modal-item">
+        <span>{{ $t('realTimeMonitor.localRemoteStatus') }}</span>
+        <span>{{ deviceRealTimeData[DevParamCoolingPump.本地远程状态] ?? '-' }}</span>
+      </div>
+      <div class="dev-ctrl-modal-item">
+        <span>{{ $t('realTimeMonitor.activePower') }}</span>
+        <span>{{ deviceRealTimeData[DevParamCoolingPump.有功功率] ?? '-' }}kw</span>
+      </div>
+      <div class="dev-ctrl-modal-item">
+        <span>{{ $t('realTimeMonitor.runningTime') }}</span>
+        <span>{{ deviceRealTimeData[DevParamCoolingPump.运行时间] ?? '-' }}{{ $t('common.hour') }}</span>
+      </div>
+    </template>
     <div class="dev-ctrl-modal-separator"></div>
     <div class="dev-ctrl-modal-item">
       <span></span>
@@ -100,11 +242,21 @@ defineExpose({
     </div>
     <div class="dev-ctrl-modal-item">
       <span>{{ $t('realTimeMonitor.enableDisable') }}</span>
-      <ASwitch />
+      <ASwitch
+        :checked="deviceRealTimeData.disableEnableStatus"
+        :checked-value="1"
+        :un-checked-value="0"
+        @click="handleDisableEnableSwitch"
+      />
     </div>
     <div class="dev-ctrl-modal-item">
       <span>{{ $t('realTimeMonitor.autoManual') }}</span>
-      <ASwitch />
+      <ASwitch
+        :checked="deviceRealTimeData.manualAutoStatus"
+        :checked-value="1"
+        :un-checked-value="0"
+        @click="handleAutoManualSwitch"
+      />
     </div>
     <div class="dev-ctrl-modal-item">
       <span>{{ $t('realTimeMonitor.startStopControl') }}</span>
@@ -113,17 +265,36 @@ defineExpose({
           <template #title>{{ startStopTip }}</template>
           <SvgIcon v-show="disableStartStopCtrl" name="info-cirlce-o" />
         </ATooltip>
-        <ASwitch :disabled="disableStartStopCtrl" />
+        <ASwitch
+          :checked="deviceRealTimeData.startStopOrder"
+          :checked-value="1"
+          :un-checked-value="0"
+          :disabled="disableStartStopCtrl"
+          @click="handleStartStopSwitch"
+        />
       </span>
     </div>
-    <div class="dev-ctrl-modal-item">
-      <span>{{ $t('realTimeMonitor.chilledWaterOutletSetValue') }}</span>
-      <AInputNumber class="dev-ctrl-chiller-input" :controls="false" />
-    </div>
-    <div class="dev-ctrl-modal-item">
-      <span>{{ $t('realTimeMonitor.loadRateLimitSetValue') }}</span>
-      <AInputNumber class="dev-ctrl-chiller-input" :controls="false" />
-    </div>
+    <template v-if="deviceType === DeviceType.冷水主机">
+      <div class="dev-ctrl-modal-item">
+        <span>{{ $t('realTimeMonitor.chilledWaterOutletSetValue') }}</span>
+        <AInputNumber
+          class="dev-ctrl-chiller-input"
+          v-model:value="deviceRealTimeData[DevParamChillerUnit.冷冻水出水温度设定值]"
+          :controls="false"
+          @change="updateDeviceData(DevParamChillerUnit.冷冻水出水温度设定值, $event)"
+        />
+      </div>
+      <div class="dev-ctrl-modal-item">
+        <span>{{ $t('realTimeMonitor.loadRateLimitSetValue') }}</span>
+        <AInputNumber
+          class="dev-ctrl-chiller-input"
+          v-model:value="deviceRealTimeData[DevParamChillerUnit.负载率限制设定值]"
+          :controls="false"
+          @change="updateDeviceData(DevParamChillerUnit.负载率限制设定值, $event)"
+        />
+      </div>
+    </template>
+    <ASpin v-if="isLoading" class="center-loading" :spinning="true" />
   </AModal>
 </template>
 

+ 15 - 4
src/views/real-time-monitor/RealTimeMonitor.vue

@@ -1,10 +1,12 @@
 <script setup lang="ts">
 import { onMounted, ref, useTemplateRef } from 'vue';
+import { message } from 'ant-design-vue';
 
 import Visual2DEditor from '@/components/visual-2d/Visual2DEditor.vue';
 import Visual2DPreview from '@/components/visual-2d/Visual2DPreview.vue';
 import { useRequest } from '@/hooks/request';
-import { getGroupModuleInfo, getPageList, noPaginationDevicesList } from '@/api';
+import { t } from '@/i18n';
+import { equipmentDetails, getGroupModuleInfo, getPageList, noPaginationDevicesList } from '@/api';
 import { VisualModuleType } from '@/constants';
 
 import DeviceControl from './device-control/DeviceControl.vue';
@@ -17,6 +19,7 @@ import type {
   DeviceGroupItem,
   DeviceGroupTree,
   DeviceGroupTreeChild,
+  EquipmentDetailsItem,
   GroupModuleInfo,
 } from '@/types';
 
@@ -31,6 +34,7 @@ const visual2DPreviewRef = useTemplateRef('visual2DPreview');
 const { isLoading, handleRequest } = useRequest();
 const moduleInfo = ref<GroupModuleInfo>();
 const deviceList = ref<DeviceGroupTree[]>([]);
+const deviceInfo = ref<EquipmentDetailsItem>();
 
 onMounted(() => {
   handleRequest(async () => {
@@ -99,10 +103,17 @@ const openEditor = () => {
 
 const openDevCtrlModal = (id: number) => {
   if (!id) {
+    message.error(t('realTimeMonitor.unboundDevice'));
     return;
   }
 
-  deviceCtrlModalRef.value?.showView();
+  handleRequest(async () => {
+    deviceInfo.value = await equipmentDetails(id);
+
+    if (deviceInfo.value.deviceQueryVo) {
+      deviceCtrlModalRef.value?.showView();
+    }
+  });
 };
 
 const exportImg = () => {
@@ -133,8 +144,8 @@ defineExpose({
       <Visual2DEditor ref="visual2DEditor" :info="moduleInfo" :device-list="deviceList" />
     </template>
     <DeviceControl ref="deviceControl" />
-    <DeviceCtrlModal ref="deviceCtrlModal" @open-dev-batch-exe="deviceBatchExeRef?.showView" />
-    <DeviceBatchExe ref="deviceBatchExe" />
+    <DeviceCtrlModal ref="deviceCtrlModal" :info="deviceInfo" @open-dev-batch-exe="deviceBatchExeRef?.showView" />
+    <DeviceBatchExe ref="deviceBatchExe" :group-id="props.deviceGroupId" />
     <ASpin v-if="isLoading" class="center-loading" :spinning="true" />
   </div>
 </template>