瀏覽代碼

perf(views): 优化“环境监控”模块

1.新增监测点状态配置。
2.室外新风温湿度仪表配置。
3.优化时间轴刻度10分钟一格共。
4.修复再次添加监测点的值未清空问题。
5.修复监测点,区域提交未刷新问题。
6.优化监测点历史数据曲线最大值与最小值根据数据波动。
7.优化批量设置温湿度限值操作逻辑,支持下拉框批量选择。
8.优化样式与文本显示
wangshun 1 月之前
父節點
當前提交
524b9d9993
共有 4 個文件被更改,包括 542 次插入94 次删除
  1. 9 0
      src/constants/index.ts
  2. 10 1
      src/i18n/locales/zh.json
  3. 73 14
      src/types/index.ts
  4. 450 79
      src/views/env-monitor/EnvMonitor.vue

+ 9 - 0
src/constants/index.ts

@@ -66,6 +66,7 @@ export const enum DictCode {
   DcCsCasType = 'dc_cs_cas_type',
   DcCsCoolingType = 'dc_cs_cooling_type',
   DcVfdType = 'dc_vfd_type',
+  ParamAlgOperator = 'param_alg_operator',
 }
 
 /**
@@ -86,10 +87,18 @@ export const enum HumitureType {
    * 送风温湿度
    */
   SupplyAir,
+  /**
+   * 新风温湿度
+   */
+  FreshAir,
   /**
    * 室外温湿度
    */
   Outdoor,
+  /**
+   * 运行状态
+   */
+  OperatingStatus,
 }
 
 /**

+ 10 - 1
src/i18n/locales/zh.json

@@ -418,7 +418,7 @@
   },
   "envMonitor": {
     "addArea": "添加区域",
-    "addInspectionPoints": "添加测点",
+    "addInspectionPoints": "添加测点",
     "averageIndoorTemperature": "室内平均温度",
     "cannotCopyEmptyCanvas": "当前画布数据为空,无法复制",
     "cardDisplay": "切换到卡片显示",
@@ -431,7 +431,10 @@
     "enableTemperatureAlertSystem": "启用温度预警",
     "exceedStandard": "超标",
     "excellent": "优",
+    "fanAirHumiditySetting": "送风湿度设置",
+    "fanTemperatureSetting": "送风温度设置",
     "humidity": "湿度",
+    "humidityTemperatureControl": "湿温度控制模式",
     "indoor": "室内",
     "indoorAverageHumidity": "室内平均湿度",
     "indoorHumiditySetting": "室内湿度配置",
@@ -446,7 +449,10 @@
     "minTrigger": "min时,触发",
     "minimumIndoorHumidityLevel": "室内湿度下限值",
     "monitoringPoint": "个监测点,",
+    "monitoringPointStatusConfiguration": "监测点状态配置",
+    "newAirTemperatureAndHumidityMeter": "室外新风温湿度仪表",
     "normal": "正常",
+    "operationStatusDetermination": "运行状态判断",
     "outdoorHumidity": "室外湿度",
     "outdoorHumidityGreaterThan": "室内温度大于",
     "outdoorTemperature": "室外温度",
@@ -457,6 +463,7 @@
     "plzSelectRegion": "请选择你要复制到的区域",
     "region": "区域",
     "regionName": "区域名",
+    "returnAirTemperatureDifference": "送回风温差",
     "returnControl": "回风控制",
     "returnCurrent": "返回当前",
     "returnTemperatureAndhumidity": "回风温湿度仪表",
@@ -471,7 +478,9 @@
     "supplyControl": "送风控制",
     "supplyTemperatureAndhumidity": "送风温湿度仪表",
     "temperature": "温度",
+    "temperatureDifferenceJudgment": "温差判断",
     "temperatureHumidityStandard": "个温湿度超标",
+    "upperLimitAirSupplyTemperatureDifference": "送风与上限温差",
     "upperLimitValue": "上限值",
     "upperLimitValueIndoorHumidity": "室内湿度上限值",
     "upperLimitValueIndoorTemperature": "室内温度上限值",

+ 73 - 14
src/types/index.ts

@@ -1488,13 +1488,24 @@ export interface MonitoringForm {
   supplyDevId?: number;
   supplyTempParamCode: string;
   supplyHumidityParamCode: string;
-  tempUpper: number;
-  tempLower: number;
-  tempPreset: number;
-  humidityUpper: number;
-  humidityLower: number;
-  humidityPreset: number;
+  outdoorDevGroupId?: number;
+  outdoorDevId?: number;
+  outdoorTempParamCode: string;
+  outdoorHumidityParamCode: string;
+  tempUpper?: number;
+  tempLower?: number;
+  tempPreset?: number;
+  humidityUpper?: number;
+  humidityLower?: number;
+  humidityPreset?: number;
   runStatusFlag: number;
+  supplyReturnTempDiff?: number;
+  supplyUpperTempDiff?: number;
+  runStatusDevGroupId?: number;
+  runStatusDevId?: number;
+  runStatusParamCode: string;
+  runStatusConditionCode: string;
+  runStatusConditionValue: string;
 }
 
 export interface RegionQuery {
@@ -1565,6 +1576,8 @@ export interface MonitoringPointData {
   tempData: CurvedData[];
   humidityData: CurvedData[];
   regionId: number;
+  humidityExStatus: number;
+  tempExStatus: number;
 }
 
 export interface CurvedData {
@@ -1583,6 +1596,8 @@ export interface MonitorPointInfo extends MonitoringForm {
   supplyDevGroupId: number;
   returnDevId: number;
   supplyDevId: number;
+  outdoorDevGroupId: number;
+  outdoorDevId: number;
 }
 
 export interface RegionNameList {
@@ -1602,13 +1617,15 @@ export interface OutdooForm {
 export interface LimitForm {
   id?: number;
   regionId?: number;
-  tempUpper: number;
-  tempLower: number;
-  tempPreset: number;
-  humidityUpper: number;
-  humidityLower: number;
-  humidityPreset: number;
+  tempUpper?: number;
+  tempLower?: number;
+  tempPreset?: number;
+  humidityUpper?: number;
+  humidityLower?: number;
+  humidityPreset?: number;
   batch: boolean;
+  batchPointIds: string;
+  batchIds?: number[];
 }
 
 export interface WarningItem {
@@ -1616,8 +1633,8 @@ export interface WarningItem {
   pointId?: number;
   enabled: boolean;
   type: number;
-  val: number;
-  duration: number;
+  val?: number;
+  duration?: number;
 }
 
 export interface MonitorPointItem extends WarningItem {
@@ -2021,3 +2038,45 @@ export interface AlgorithmConfigInfo extends AlgorithmForm {
   chilledWaterOutletTempRangeList: TemperatureRangeItem[];
   chilledWaterOutletTempSet: string;
 }
+
+export interface OrgDeviceLimit {
+  deviceGlobalId?: number;
+  upperLimit?: number;
+}
+
+export interface OrganizationItem {
+  id?: number;
+  orgName: string;
+  orderNum?: number;
+  logo?: string;
+  themeColor?: string;
+  startTenancy?: string;
+  endTenancy?: string;
+  dataValidityPeriod?: string;
+  remark?: string;
+  enabled?: string;
+  orgDeviceLimits?: OrgDeviceLimit[];
+}
+export interface CreateCustomer {
+  organizationName: string;
+  color: string;
+}
+
+export interface CharacterItem {
+  name: string;
+  id?: number;
+}
+
+export interface AccountItem {
+  name: string;
+}
+
+export interface DeviceParamType {
+  id: number;
+  deviceParamCode: string;
+  deviceParamName: string;
+  unit: string;
+  codeType: number;
+  type: number;
+  candidates: string[];
+}

+ 450 - 79
src/views/env-monitor/EnvMonitor.vue

@@ -7,6 +7,7 @@ import { message } from 'ant-design-vue';
 import ButtonTabs from '@/components/ButtonTabs.vue';
 import LineChart from '@/components/LineChart.vue';
 import SvgIcon from '@/components/SvgIcon.vue';
+import { useDictData } from '@/hooks/dict-data';
 import { useRequest } from '@/hooks/request';
 import { t } from '@/i18n';
 import {
@@ -14,6 +15,7 @@ import {
   addRegion,
   deleteMonitorPoint,
   getDeviceGroupList,
+  getDeviceListOptions,
   getDeviceListSimple,
   getGroupRegions,
   getMonitorPointAlarmHistory,
@@ -27,9 +29,7 @@ import {
   updateMonitorPoint,
   updateRegionMonitorPoint,
 } from '@/api';
-import { HumitureType } from '@/constants';
-
-import envMonitorBgc from '@/assets/img/env-monitor-bgc.png';
+import { DictCode, HumitureType } from '@/constants';
 
 import AreaEditor from './AreaEditor.vue';
 import AreaPreview from './AreaPreview.vue';
@@ -45,7 +45,9 @@ import type {
   DeviceGroup,
   DeviceGroupItem,
   DeviceParams,
+  DeviceParamType,
   DevicesListItem,
+  DictValue,
   GroupRegions,
   MonitoringForm,
   MonitoringPointData,
@@ -54,11 +56,6 @@ import type {
   RegionsPointsItem,
 } from '@/types';
 
-interface EnvMonitorStyle {
-  background: string;
-  backgroundSize: string;
-}
-
 interface TimeList {
   time: string;
   integral: boolean;
@@ -66,11 +63,18 @@ interface TimeList {
   backgroundShow: boolean;
 }
 
-const envMonitorListRef = useTemplateRef('envMonitorList');
+interface RunStatusList {
+  id: number;
+  name: string;
+}
 
+const { dictData: paramAlgOperator, getDictData: getParamAlgOperator } = useDictData(DictCode.ParamAlgOperator);
+const envMonitorListRef = useTemplateRef('envMonitorList');
+const temperatureDifference = ref<DictValue[]>([]);
 const oneDeviceGroup = ref<DeviceGroup[]>([]);
 const twoDeviceGroup = ref<DeviceGroup[]>([]);
-
+const runStatusList = ref<RunStatusList[]>([]);
+const inputType = ref<number>(1);
 const gradeOne = ref<number | undefined>(undefined);
 const gradeTwo = ref<number | undefined>(undefined);
 const monitoringPointOpen = ref<boolean>(false);
@@ -79,6 +83,7 @@ const regionNameOpen = ref<boolean>(false);
 const monitoringDataOpen = ref<boolean>(false);
 const regionCopyOpen = ref<boolean>(false);
 const regionName = ref<string>('');
+const regionNameEditor = ref<string>('');
 const groupRegions = ref<GroupRegions[]>([]);
 const titleRegions = ref<boolean>(true);
 const titleMonitoring = ref<boolean>(true);
@@ -86,9 +91,14 @@ const deviceGroup = ref<DeviceGroupItem[]>([]);
 const returnDevicesList = ref<DevicesListItem[]>([]);
 const supplyDevicesList = ref<DevicesListItem[]>([]);
 const outdoorDevicesList = ref<DevicesListItem[]>([]);
+const freshDevicesList = ref<DevicesListItem[]>([]);
+const runDevicesList = ref<DevicesListItem[]>([]);
 const returnDeviceParamsList = ref<DeviceParams[]>([]);
 const supplyDeviceParamsList = ref<DeviceParams[]>([]);
 const outdoorDeviceParamsList = ref<DeviceParams[]>([]);
+const freshDeviceParamsList = ref<DeviceParams[]>([]);
+const runDeviceParamsList = ref<DeviceParamType[]>([]);
+
 const monitoringPointData = ref<MonitoringPointData[]>([]);
 const regionNameList = ref<RegionNameList[]>([]);
 const regionList = ref<RegionsPointsItem[]>([]);
@@ -104,11 +114,6 @@ const monitoringPointList = ref<MonitoringPointData[]>([]);
 const chooseTime = ref<string>();
 const alarmHistoryList = ref<AlarmHistoryItem[]>([]);
 
-const envMonitorStyle = ref<EnvMonitorStyle>({
-  background: `url(${envMonitorBgc})`,
-  backgroundSize: 'cover',
-});
-
 const monitoringForm = ref<MonitoringForm>({
   name: '',
   tempHumidityControlMode: '2',
@@ -120,12 +125,24 @@ const monitoringForm = ref<MonitoringForm>({
   supplyDevGroupId: undefined,
   supplyTempParamCode: '',
   supplyHumidityParamCode: '',
-  tempUpper: 0,
-  tempLower: 0,
-  tempPreset: 0,
-  humidityUpper: 0,
-  humidityLower: 0,
-  humidityPreset: 0,
+  outdoorDevGroupId: undefined,
+  outdoorDevId: undefined,
+  outdoorTempParamCode: '',
+  outdoorHumidityParamCode: '',
+  tempUpper: undefined,
+  tempLower: undefined,
+  tempPreset: undefined,
+  humidityUpper: undefined,
+  humidityLower: undefined,
+  humidityPreset: undefined,
+  runStatusFlag: 0,
+  supplyReturnTempDiff: undefined,
+  supplyUpperTempDiff: undefined,
+  runStatusDevGroupId: undefined,
+  runStatusDevId: undefined,
+  runStatusParamCode: '',
+  runStatusConditionCode: '',
+  runStatusConditionValue: '',
 });
 
 const outdooForm = ref<OutdooForm>({
@@ -150,6 +167,8 @@ const footerStyle: CSSProperties = {
 const rules: Record<string, Rule[]> = {
   name: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
   regionId: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
+  tempHumidityControlMode: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
+
   returnDevGroupId: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
   returnDevId: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
   returnTempParamCode: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
@@ -158,6 +177,13 @@ const rules: Record<string, Rule[]> = {
   supplyDevId: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
   supplyTempParamCode: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
   supplyHumidityParamCode: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
+  outdoorDevGroupId: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
+  outdoorDevId: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
+  outdoorTempParamCode: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
+  outdoorHumidityParamCode: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
+  runStatusFlag: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
+  supplyReturnTempDiff: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
+  supplyUpperTempDiff: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
 };
 
 const { handleRequest } = useRequest();
@@ -182,13 +208,16 @@ const regionNameOk = () => {
           regionName: regionName.value,
         });
       } else {
-        await regionUpdate({
-          id: monitoringForm.value.regionId,
-          devGroupId: gradeTwo.value,
-          regionName: regionName.value,
-        });
+        if (regionNameEditor.value != regionName.value) {
+          await regionUpdate({
+            id: monitoringForm.value.regionId,
+            devGroupId: gradeTwo.value,
+            regionName: regionName.value,
+          });
+        }
       }
       getGroupRegionsList();
+      obtainRegionsPointsData(gradeTwo.value);
       regionNameOpen.value = false;
     }
   });
@@ -203,6 +232,10 @@ const regionNameDelete = () => {
       await regionDelete(monitoringForm.value.regionId);
       monitoringForm.value.regionId = undefined;
       getGroupRegionsList();
+      if (gradeTwo.value) {
+        obtainRegionsPointsData(gradeTwo.value);
+      }
+
       regionNameOpen.value = false;
     }
   });
@@ -215,11 +248,17 @@ const addRegionName = () => {
 };
 
 const addRegionList = (value: SelectValue, option: DefaultOptionType) => {
+  regionNameEditor.value = option.regionName;
   regionName.value = option.regionName;
 };
 
 const editingRegionName = () => {
   if (monitoringForm.value.regionId) {
+    groupRegions.value.forEach((item) => {
+      if (item.id === monitoringForm.value.regionId) {
+        regionName.value = item.regionName;
+      }
+    });
     titleRegions.value = false;
     regionNameOpen.value = true;
   } else {
@@ -273,8 +312,8 @@ const getRegionsPointsList = (value: number) => {
       if (monitoringPointData.value.length) {
         monitoringPointData.value.sort((item1, item2) => {
           // 优先级:3 > 2 > 其他
-          const priority1 = item1.status === 3 ? 1 : item1.status === 2 ? 2 : 3;
-          const priority2 = item2.status === 3 ? 1 : item2.status === 2 ? 2 : 3;
+          const priority1 = item1.status === 3 ? 1 : item1.status === 2 ? 2 : item1.status === 1 ? 3 : 4;
+          const priority2 = item2.status === 3 ? 1 : item2.status === 2 ? 2 : item2.status === 1 ? 3 : 4;
 
           return priority1 - priority2;
         });
@@ -292,35 +331,69 @@ const obtainRegionsPointsData = (value: number) => {
 };
 
 const adddDeviceGroup = (value: SelectValue, option: DefaultOptionType, judgment: number) => {
-  getDevicesGroupList(option.id, judgment);
+  getDevicesGroupList(option.id, judgment, true);
 };
 
 const adddDevice = (value: SelectValue, option: DefaultOptionType, judgment: number) => {
-  getDeviceParamsList(option.id, judgment);
+  getDeviceParamsList(option.id, judgment, true);
+};
+
+const adddRunStatusDevice = (value: SelectValue, option: DefaultOptionType) => {
+  monitoringForm.value.runStatusParamCode = '';
+  monitoringForm.value.runStatusConditionCode = '';
+  monitoringForm.value.runStatusConditionValue = '';
+  handleRequest(async () => {
+    runDeviceParamsList.value = await getDeviceListOptions(option.id);
+  });
 };
 
-const getDeviceParamsList = (id: number, judgment: number) => {
+const adddParametersDevice = (value: SelectValue, option: DefaultOptionType) => {
+  runStatusList.value = [];
+  inputType.value = option.type;
+  if (option.type === 1) {
+    option.candidates.forEach((item: string, index: number) => {
+      runStatusList.value.push({
+        id: index,
+        name: item,
+      });
+    });
+  }
+};
+
+const getDeviceParamsList = (id: number, judgment: number, show: boolean) => {
   handleRequest(async () => {
     const data = await getDeviceListSimple(id);
 
     if (judgment === HumitureType.ReturnAir) {
       returnDeviceParamsList.value = data;
-      monitoringForm.value.returnHumidityParamCode = '';
-      monitoringForm.value.returnTempParamCode = '';
+      if (show) {
+        monitoringForm.value.returnHumidityParamCode = '';
+        monitoringForm.value.returnTempParamCode = '';
+      }
     } else if (judgment === HumitureType.SupplyAir) {
       supplyDeviceParamsList.value = data;
-      monitoringForm.value.supplyHumidityParamCode = '';
-      monitoringForm.value.supplyTempParamCode = '';
+      if (show) {
+        monitoringForm.value.supplyHumidityParamCode = '';
+        monitoringForm.value.supplyTempParamCode = '';
+      }
     } else if (judgment === HumitureType.Outdoor) {
       outdoorDeviceParamsList.value = data;
-      outdooForm.value.outsideEnthalpyParamCode = '';
-      outdooForm.value.outsideHumidityParamCode = '';
-      outdooForm.value.outsideTempParamCode = '';
+      if (show) {
+        outdooForm.value.outsideEnthalpyParamCode = '';
+        outdooForm.value.outsideHumidityParamCode = '';
+        outdooForm.value.outsideTempParamCode = '';
+      }
+    } else if (judgment === HumitureType.FreshAir) {
+      freshDeviceParamsList.value = data;
+      if (show) {
+        monitoringForm.value.outdoorTempParamCode = '';
+        monitoringForm.value.outdoorHumidityParamCode = '';
+      }
     }
   });
 };
 
-const getDevicesGroupList = (id: number, judgment: number) => {
+const getDevicesGroupList = (id: number, judgment: number, show: boolean) => {
   handleRequest(async () => {
     const { records } = await queryDevicesList({
       pageIndex: 1,
@@ -329,20 +402,41 @@ const getDevicesGroupList = (id: number, judgment: number) => {
     });
     if (judgment === HumitureType.ReturnAir) {
       returnDevicesList.value = records;
-      monitoringForm.value.returnDevId = undefined;
-      monitoringForm.value.returnHumidityParamCode = '';
-      monitoringForm.value.returnTempParamCode = '';
+      if (show) {
+        monitoringForm.value.returnDevId = undefined;
+        monitoringForm.value.returnHumidityParamCode = '';
+        monitoringForm.value.returnTempParamCode = '';
+      }
     } else if (judgment === HumitureType.SupplyAir) {
       supplyDevicesList.value = records;
-      monitoringForm.value.supplyDevId = undefined;
-      monitoringForm.value.supplyHumidityParamCode = '';
-      monitoringForm.value.supplyTempParamCode = '';
+      if (show) {
+        monitoringForm.value.supplyDevId = undefined;
+        monitoringForm.value.supplyHumidityParamCode = '';
+        monitoringForm.value.supplyTempParamCode = '';
+      }
     } else if (judgment === HumitureType.Outdoor) {
       outdoorDevicesList.value = records;
-      outdooForm.value.outsideDevId = undefined;
-      outdooForm.value.outsideEnthalpyParamCode = '';
-      outdooForm.value.outsideHumidityParamCode = '';
-      outdooForm.value.outsideTempParamCode = '';
+      if (show) {
+        outdooForm.value.outsideDevId = undefined;
+        outdooForm.value.outsideEnthalpyParamCode = '';
+        outdooForm.value.outsideHumidityParamCode = '';
+        outdooForm.value.outsideTempParamCode = '';
+      }
+    } else if (judgment === HumitureType.FreshAir) {
+      freshDevicesList.value = records;
+      if (show) {
+        monitoringForm.value.outdoorDevId = undefined;
+        monitoringForm.value.outdoorTempParamCode = '';
+        monitoringForm.value.outdoorHumidityParamCode = '';
+      }
+    } else if (judgment === HumitureType.OperatingStatus) {
+      runDevicesList.value = records;
+      if (show) {
+        monitoringForm.value.runStatusDevId = undefined;
+        monitoringForm.value.runStatusParamCode = '';
+        monitoringForm.value.runStatusConditionCode = '';
+        monitoringForm.value.runStatusConditionValue = '';
+      }
     }
   });
 };
@@ -351,6 +445,11 @@ const deleteMonitoringPoint = () => {
     handleRequest(async () => {
       if (monitoringId.value) {
         await deleteMonitorPoint(monitoringId.value);
+        if (gradeTwo.value) {
+          getRegionsPointsList(gradeTwo.value);
+          timeLineIndex.value = timeList.value.length - 1;
+        }
+        closeModal();
       }
     });
   }
@@ -364,13 +463,16 @@ const saveMonitoringPoint = () => {
     .then(() => {
       handleRequest(async () => {
         if (titleMonitoring.value) {
+          delete monitoringForm.value.id;
           await addMonitorPoint(monitoringForm.value);
         } else {
           await updateMonitorPoint(monitoringForm.value);
         }
         if (gradeTwo.value) {
           getRegionsPointsList(gradeTwo.value);
+          obtainRegionsPointsData(gradeTwo.value);
         }
+        closeModal();
         monitoringPointOpen.value = false;
       });
     })
@@ -385,6 +487,7 @@ const getDeviceGroup = () => {
 
 const offDrawer = () => {
   monitoringPointOpen.value = false;
+  closeModal();
 };
 
 const selectClick = (id: number) => {
@@ -420,6 +523,18 @@ const editorClick = (monitoringPointId: number) => {
       tempPreset,
       tempUpper,
       id,
+      outdoorDevGroupId,
+      outdoorDevId,
+      outdoorTempParamCode,
+      outdoorHumidityParamCode,
+      runStatusFlag,
+      supplyReturnTempDiff,
+      supplyUpperTempDiff,
+      runStatusDevGroupId,
+      runStatusDevId,
+      runStatusParamCode,
+      runStatusConditionCode,
+      runStatusConditionValue,
     } = await getMonitorPointInfo(monitoringPointId);
     Object.assign(monitoringForm.value, {
       humidityLower,
@@ -440,19 +555,82 @@ const editorClick = (monitoringPointId: number) => {
       tempPreset,
       tempUpper,
       id,
+      outdoorDevGroupId,
+      outdoorDevId,
+      outdoorTempParamCode,
+      outdoorHumidityParamCode,
+      runStatusFlag,
+      supplyReturnTempDiff,
+      supplyUpperTempDiff,
+      runStatusDevGroupId,
+      runStatusDevId,
+      runStatusParamCode,
+      runStatusConditionCode,
+      runStatusConditionValue,
     });
     monitoringId.value = id;
-    getDevicesGroupList(returnDevGroupId, HumitureType.ReturnAir);
-    getDevicesGroupList(supplyDevGroupId, HumitureType.SupplyAir);
+    getDevicesGroupList(returnDevGroupId, HumitureType.ReturnAir, false);
+    getDevicesGroupList(supplyDevGroupId, HumitureType.SupplyAir, false);
+    if (monitoringForm.value.tempHumidityControlMode === '1') {
+      getDevicesGroupList(outdoorDevGroupId, HumitureType.FreshAir, false);
+    }
 
-    getDeviceParamsList(returnDevId, HumitureType.ReturnAir);
-    getDeviceParamsList(supplyDevId, HumitureType.SupplyAir);
+    getDeviceParamsList(returnDevId, HumitureType.ReturnAir, false);
+    getDeviceParamsList(supplyDevId, HumitureType.SupplyAir, false);
 
+    if (monitoringForm.value.tempHumidityControlMode === '1') {
+      getDeviceParamsList(outdoorDevId, HumitureType.FreshAir, false);
+    }
     titleMonitoring.value = false;
     monitoringPointOpen.value = true;
   });
 };
 
+const closeModal = () => {
+  returnDevicesList.value = [];
+  returnDeviceParamsList.value = [];
+  supplyDevicesList.value = [];
+  supplyDeviceParamsList.value = [];
+  freshDevicesList.value = [];
+  freshDeviceParamsList.value = [];
+  runDevicesList.value = [];
+  runDeviceParamsList.value = [];
+  runStatusList.value = [];
+
+  monitoringForm.value = {
+    name: '',
+    tempHumidityControlMode: '2',
+    regionId: undefined,
+    returnDevGroupId: undefined,
+    returnDevId: undefined,
+    returnTempParamCode: '',
+    returnHumidityParamCode: '',
+    supplyDevGroupId: undefined,
+    supplyTempParamCode: '',
+    supplyHumidityParamCode: '',
+    outdoorDevGroupId: undefined,
+    outdoorDevId: undefined,
+    outdoorTempParamCode: '',
+    outdoorHumidityParamCode: '',
+    tempUpper: undefined,
+    tempLower: undefined,
+    tempPreset: undefined,
+    humidityUpper: undefined,
+    humidityLower: undefined,
+    humidityPreset: undefined,
+    runStatusFlag: 0,
+    supplyReturnTempDiff: undefined,
+    supplyUpperTempDiff: undefined,
+    runStatusDevGroupId: undefined,
+    runStatusDevId: undefined,
+    runStatusParamCode: '',
+    runStatusConditionCode: '',
+    runStatusConditionValue: '',
+  };
+
+  formRef.value?.resetFields();
+};
+
 const addOutdoorDrawer = () => {
   outdoorOpen.value = true;
   regionList.value.forEach((item) => {
@@ -474,11 +652,11 @@ const addOutdoorDrawer = () => {
         regionId: id,
       });
       if (outsideDevGroupId) {
-        getDevicesGroupList(outsideDevGroupId, HumitureType.Outdoor);
+        getDevicesGroupList(outsideDevGroupId, HumitureType.Outdoor, true);
       }
 
       if (outsideDevId) {
-        getDeviceParamsList(outsideDevId, HumitureType.Outdoor);
+        getDeviceParamsList(outsideDevId, HumitureType.Outdoor, true);
       }
     }
   });
@@ -521,7 +699,7 @@ const generateTimeArray = async () => {
   const now = new Date();
   const currentHour = now.getHours();
   const currentMinute = now.getMinutes();
-  const minutes = [0, 12, 24, 36, 48];
+  const minutes = [0, 10, 20, 30, 40, 50];
   const result = [];
   let index = 0;
 
@@ -608,6 +786,7 @@ const returnCurrently = () => {
     if (maxScrollX > 0) {
       bs?.scrollTo(-maxScrollX, 0, 800);
     }
+    timeLineIndex.value = timeList.value.length - 1;
   }
 };
 
@@ -632,10 +811,12 @@ const confirmTimeLine = () => {
         monitoringPointList.value = await getRegionsPointsValue(gradeTwo.value, {
           endTime: `${getCurrentDate()} ${chooseTime.value}:00`,
         });
-        mergeData();
-        monitoringPointData.value = monitoringPointList.value;
-        monitoringId.value = monitoringPointData.value[0].id;
-        selectId.value = monitoringPointData.value[0].regionId;
+        if (monitoringPointList.value.length) {
+          mergeData();
+          monitoringPointData.value = monitoringPointList.value;
+          monitoringId.value = monitoringPointData.value[0].id;
+          selectId.value = monitoringPointData.value[0].regionId;
+        }
       }
     }
   });
@@ -716,6 +897,15 @@ onMounted(() => {
   getDeviceGroup();
   generateTimeArray();
   initScroll();
+  handleRequest(async () => {
+    temperatureDifference.value = [];
+    await getParamAlgOperator();
+    paramAlgOperator.value.forEach((item) => {
+      if (item.dictValueId === 250 || item.dictValueId === 251) {
+        temperatureDifference.value.push(item);
+      }
+    });
+  });
 });
 
 const areaEditorRef = useTemplateRef('areaEditor');
@@ -886,7 +1076,7 @@ const copyAreaCanvas = () => {
           </div>
         </div>
 
-        <AFlex :style="envMonitorStyle" class="monitoring-img">
+        <AFlex class="monitoring-img">
           <AFlex v-show="regionList.length" align="center" class="list-regions">
             <ButtonTabs
               :data="regionNameList"
@@ -959,7 +1149,7 @@ const copyAreaCanvas = () => {
           <AInput
             v-model:value="monitoringForm.name"
             class="input-wdith region-bottom"
-            :placeholder="$t('common.plzSelect')"
+            :placeholder="$t('common.pleaseEnter')"
           />
         </AFormItem>
         <AFormItem :label="$t('envMonitor.region')" name="regionId">
@@ -985,10 +1175,13 @@ const copyAreaCanvas = () => {
             </div>
           </AFlex>
         </AFormItem>
-        <ARadioGroup v-model:value="monitoringForm.tempHumidityControlMode" class="radio-group">
-          <ARadio value="2">{{ $t('envMonitor.returnControl') }}</ARadio>
-          <ARadio value="1">{{ $t('envMonitor.supplyControl') }}</ARadio>
-        </ARadioGroup>
+        <AFormItem :label="t('envMonitor.humidityTemperatureControl')" name="tempHumidityControlMode">
+          <ARadioGroup v-model:value="monitoringForm.tempHumidityControlMode" class="radio-group">
+            <ARadio value="2">{{ $t('envMonitor.returnControl') }}</ARadio>
+            <ARadio value="1">{{ $t('envMonitor.supplyControl') }}</ARadio>
+          </ARadioGroup>
+        </AFormItem>
+
         <AFlex justify="space-between">
           <div>
             <AFormItem class="form-item" :label="$t('envMonitor.returnTemperatureAndhumidity')" name="returnDevGroupId">
@@ -1073,18 +1266,81 @@ const copyAreaCanvas = () => {
             </AFormItem>
           </div>
         </AFlex>
+        <div v-if="monitoringForm.tempHumidityControlMode === '1'">
+          <AFormItem
+            class="form-item"
+            :label="t('envMonitor.newAirTemperatureAndHumidityMeter')"
+            name="outdoorDevGroupId"
+          >
+            <ASelect
+              class="input-wdith"
+              v-model:value="monitoringForm.outdoorDevGroupId"
+              :options="twoDeviceGroup"
+              :field-names="{ label: 'groupName', value: 'id' }"
+              :placeholder="$t('common.plzSelect')"
+              @change="(value, option) => adddDeviceGroup(value, option, HumitureType.FreshAir)"
+            />
+          </AFormItem>
+          <AFormItem name="outdoorDevId">
+            <ASelect
+              class="input-wdith"
+              v-model:value="monitoringForm.outdoorDevId"
+              :options="freshDevicesList"
+              :field-names="{ label: 'deviceName', value: 'id' }"
+              :placeholder="$t('common.plzSelect')"
+              @change="(value, option) => adddDevice(value, option, HumitureType.FreshAir)"
+            />
+          </AFormItem>
 
-        <AFlex justify="space-between">
-          <div>
-            <AFormItem :label="$t('envMonitor.indoorTemperatureConfiguration')">
+          <AFormItem name="outdoorTempParamCode">
+            <ASelect
+              class="input-wdith"
+              v-model:value="monitoringForm.outdoorTempParamCode"
+              :options="freshDeviceParamsList"
+              :field-names="{ label: 'deviceParamName', value: 'deviceParamCode' }"
+              :placeholder="$t('common.plzSelect')"
+            />
+          </AFormItem>
+          <AFormItem name="outdoorHumidityParamCode">
+            <ASelect
+              class="input-wdith"
+              v-model:value="monitoringForm.outdoorHumidityParamCode"
+              :options="freshDeviceParamsList"
+              :field-names="{ label: 'deviceParamName', value: 'deviceParamCode' }"
+              :placeholder="$t('common.plzSelect')"
+            />
+          </AFormItem>
+        </div>
+
+        <AFlex>
+          <div class="spacing-right">
+            <AFormItem
+              :label="
+                monitoringForm.tempHumidityControlMode === '1'
+                  ? $t('envMonitor.fanTemperatureSetting')
+                  : $t('envMonitor.indoorTemperatureConfiguration')
+              "
+            >
               <AFlex align="center">
-                <AInputNumber class="input-number-width" v-model:value="monitoringForm.tempUpper" :min="0" :max="999" />
+                <AInputNumber
+                  class="input-number-width"
+                  :placeholder="$t('common.pleaseEnter')"
+                  v-model:value="monitoringForm.tempUpper"
+                  :min="0"
+                  :max="999"
+                />
                 <div class="configure-text">{{ $t('envMonitor.upperLimitValue') }}</div>
               </AFlex>
             </AFormItem>
             <AFormItem>
               <AFlex align="center">
-                <AInputNumber class="input-number-width" v-model:value="monitoringForm.tempLower" :min="0" :max="999" />
+                <AInputNumber
+                  class="input-number-width"
+                  :placeholder="$t('common.pleaseEnter')"
+                  v-model:value="monitoringForm.tempLower"
+                  :min="0"
+                  :max="999"
+                />
                 <div class="configure-text">{{ $t('envMonitor.lowerLimitValue') }}</div>
               </AFlex>
             </AFormItem>
@@ -1095,19 +1351,27 @@ const copyAreaCanvas = () => {
                   v-model:value="monitoringForm.tempPreset"
                   :min="0"
                   :max="999"
+                  :placeholder="$t('common.pleaseEnter')"
                 />
                 <div class="configure-text">{{ $t('envMonitor.limitValue') }}</div>
               </AFlex>
             </AFormItem>
           </div>
           <div>
-            <AFormItem :label="$t('envMonitor.indoorHumiditySetting')">
+            <AFormItem
+              :label="
+                monitoringForm.tempHumidityControlMode === '1'
+                  ? t('envMonitor.fanAirHumiditySetting')
+                  : $t('envMonitor.indoorHumiditySetting')
+              "
+            >
               <AFlex align="center">
                 <AInputNumber
                   class="input-number-width"
                   v-model:value="monitoringForm.humidityUpper"
                   :min="0"
                   :max="999"
+                  :placeholder="$t('common.pleaseEnter')"
                 />
                 <div class="configure-text">{{ $t('envMonitor.upperLimitValue') }}</div>
               </AFlex>
@@ -1119,6 +1383,7 @@ const copyAreaCanvas = () => {
                   v-model:value="monitoringForm.humidityLower"
                   :min="0"
                   :max="999"
+                  :placeholder="$t('common.pleaseEnter')"
                 />
                 <div class="configure-text">{{ $t('envMonitor.lowerLimitValue') }}</div>
               </AFlex>
@@ -1130,12 +1395,105 @@ const copyAreaCanvas = () => {
                   v-model:value="monitoringForm.humidityPreset"
                   :min="0"
                   :max="999"
+                  :placeholder="$t('common.pleaseEnter')"
                 />
                 <div class="configure-text">{{ $t('envMonitor.limitValue') }}</div>
               </AFlex>
             </AFormItem>
           </div>
         </AFlex>
+        <AFormItem :label="t('envMonitor.monitoringPointStatusConfiguration')" name="runStatusFlag">
+          <ARadioGroup v-model:value="monitoringForm.runStatusFlag" class="radio-group">
+            <ARadio :value="0">{{ t('envMonitor.temperatureDifferenceJudgment') }}</ARadio>
+            <ARadio :value="1">{{ t('envMonitor.operationStatusDetermination') }}</ARadio>
+          </ARadioGroup>
+        </AFormItem>
+        <AFlex v-show="monitoringForm.runStatusFlag === 0">
+          <AFormItem name="supplyReturnTempDiff">
+            <AFlex align="center" class="spacing">
+              <AInputNumber
+                class="input-number-width"
+                v-model:value="monitoringForm.supplyReturnTempDiff"
+                :min="0"
+                :max="999"
+                :placeholder="$t('common.pleaseEnter')"
+              />
+              <div class="configure-text">{{ t('envMonitor.returnAirTemperatureDifference') }}</div>
+            </AFlex>
+          </AFormItem>
+          <AFormItem name="supplyUpperTempDiff">
+            <AFlex align="center">
+              <AInputNumber
+                class="input-number-width"
+                v-model:value="monitoringForm.supplyUpperTempDiff"
+                :min="0"
+                :max="999"
+                :placeholder="$t('common.pleaseEnter')"
+              />
+              <div class="configure-text">{{ t('envMonitor.upperLimitAirSupplyTemperatureDifference') }}</div>
+            </AFlex>
+          </AFormItem>
+        </AFlex>
+        <AFlex justify="space-between" wrap="wrap" v-show="monitoringForm.runStatusFlag === 1">
+          <AFormItem name="runStatusDevGroupId">
+            <ASelect
+              class="input-wdith"
+              v-model:value="monitoringForm.runStatusDevGroupId"
+              :options="twoDeviceGroup"
+              :field-names="{ label: 'groupName', value: 'id' }"
+              :placeholder="$t('common.plzSelect')"
+              @change="(value, option) => adddDeviceGroup(value, option, HumitureType.OperatingStatus)"
+            />
+          </AFormItem>
+          <AFormItem name="runStatusDevId">
+            <ASelect
+              class="input-wdith"
+              v-model:value="monitoringForm.runStatusDevId"
+              :options="runDevicesList"
+              :field-names="{ label: 'deviceName', value: 'id' }"
+              :placeholder="$t('common.plzSelect')"
+              @change="(value, option) => adddRunStatusDevice(value, option)"
+            />
+          </AFormItem>
+          <AFormItem name="runStatusParamCode">
+            <ASelect
+              class="input-wdith"
+              v-model:value="monitoringForm.runStatusParamCode"
+              :options="runDeviceParamsList"
+              :field-names="{ label: 'deviceParamName', value: 'deviceParamCode' }"
+              :placeholder="$t('common.plzSelect')"
+              @change="(value, option) => adddParametersDevice(value, option)"
+            />
+          </AFormItem>
+          <AFormItem name="runStatusConditionCode">
+            <ASelect
+              class="input-wdith"
+              v-model:value="monitoringForm.runStatusConditionCode"
+              :options="inputType === 1 ? temperatureDifference : paramAlgOperator"
+              :placeholder="$t('common.plzSelect')"
+              :field-names="{ label: 'dictValue', value: 'dictValue' }"
+            />
+          </AFormItem>
+          <AFormItem v-if="inputType === 1" name="runStatusConditionValue">
+            <ASelect
+              class="input-wdith"
+              v-model:value="monitoringForm.runStatusConditionValue"
+              :options="runStatusList"
+              :placeholder="$t('common.plzSelect')"
+              :field-names="{ label: 'name', value: 'name' }"
+            />
+          </AFormItem>
+
+          <AFormItem v-else name="runStatusConditionValue">
+            <AInputNumber
+              class="input-wdith"
+              v-model:value="monitoringForm.runStatusConditionValue"
+              :min="0"
+              :max="999"
+              :placeholder="$t('common.pleaseEnter')"
+            />
+          </AFormItem>
+        </AFlex>
       </AForm>
       <template #footer>
         <AFlex justify="flex-end" :gap="16">
@@ -1200,10 +1558,11 @@ const copyAreaCanvas = () => {
           <ASelect
             class="input-wdith"
             v-model:value="outdooForm.outsideEnthalpyParamCode"
-            :options="outdoorDeviceParamsList"
-            :field-names="{ label: 'deviceParamName', value: 'deviceParamCode' }"
             :placeholder="$t('common.plzSelect')"
-          />
+          >
+            <ASelectOption value="温度">{{ t('envMonitor.temperature') }}</ASelectOption>
+            <ASelectOption value="湿度">{{ t('envMonitor.humidity') }}</ASelectOption>
+          </ASelect>
         </AFormItem>
       </AForm>
       <template #footer>
@@ -1243,7 +1602,7 @@ const copyAreaCanvas = () => {
       :keyboard="false"
     >
       <div class="region-name">{{ $t('envMonitor.regionName') }}</div>
-      <AInput v-model:value="regionName" :placeholder="$t('common.plzSelect')" />
+      <AInput v-model:value="regionName" :placeholder="$t('common.pleaseEnter')" />
 
       <AFlex justify="flex-end" class="region-name-top">
         <AButton v-if="!titleRegions" class="default-button" @click="regionNameDelete">{{
@@ -1289,6 +1648,14 @@ const copyAreaCanvas = () => {
 </template>
 
 <style lang="scss" scoped>
+.spacing {
+  margin-right: 74px;
+}
+
+.spacing-right {
+  margin-right: 102px;
+}
+
 .background-default {
   height: 40px;
   background-color: #fff;
@@ -1426,6 +1793,9 @@ const copyAreaCanvas = () => {
 .monitoring-img {
   width: 100%;
   height: 100%;
+  background-image: radial-gradient(circle, #d8d8d8 1px, #fff 1px);
+  background-position: center center;
+  background-size: 15px 15px;
 }
 
 .content-monitoring-canvas {
@@ -1452,7 +1822,7 @@ const copyAreaCanvas = () => {
 }
 
 .radio-group {
-  margin: 8px 0 24px;
+  margin: 8px 0 10px;
 }
 
 .region-bottom {
@@ -1464,8 +1834,9 @@ const copyAreaCanvas = () => {
 }
 
 .input-number-width {
-  width: 192px;
-  margin-bottom: 16px;
+  width: 140px;
+
+  // margin-bottom: 16px;
 }
 
 .segmented-monitoring {