Эх сурвалжийг харах

perf(views): 优化创建设备模块

1.优化弹框下布局与样式。
2.新增删除确定弹框,查询与重置功能。
3.修复创建设备-选择网关参数逻辑处理错误问题。
4.多语言显示问题。
wangshun 1 сар өмнө
parent
commit
08ca381ec5

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

@@ -192,7 +192,7 @@
     "selectGatewayParameters": "选择网关参数",
     "selectGatewayParameters": "选择网关参数",
     "selectGatewayProtocolParameters": "选择网关协议参数",
     "selectGatewayProtocolParameters": "选择网关协议参数",
     "selectParameters": "选择参数",
     "selectParameters": "选择参数",
-    "selectionMonitoringParameters": "监测参数:已选",
+    "selectionMonitoringParameters": "数据监控:已选",
     "serviceLife": "使用年限  (年)",
     "serviceLife": "使用年限  (年)",
     "suggestion": "建议按「设备名」「序号」的方式命名,比如:电表1",
     "suggestion": "建议按「设备名」「序号」的方式命名,比如:电表1",
     "uninstallPower": "卸载功率(KW)",
     "uninstallPower": "卸载功率(KW)",

+ 7 - 7
src/types/index.ts

@@ -453,14 +453,14 @@ export interface ProtocolList {
 export interface EquipmentInformationForm {
 export interface EquipmentInformationForm {
   groupId: number;
   groupId: number;
   deviceData: number[];
   deviceData: number[];
-  deviceType: string;
+  deviceType?: string;
   deviceName: string;
   deviceName: string;
-  brand: number;
-  model: number;
-  modelType: number;
-  controlType: number;
-  compressionLevel: number;
-  voltageLevel: number;
+  brand?: number;
+  model?: number;
+  modelType?: number;
+  controlType?: number;
+  compressionLevel?: number;
+  voltageLevel?: number;
   powerRating: string;
   powerRating: string;
   powerUnload: string;
   powerUnload: string;
   maximumFlow: string;
   maximumFlow: string;

+ 25 - 26
src/views/create-device/BasicInformation.vue

@@ -36,11 +36,11 @@ onMounted(() => {
 
 
 <template>
 <template>
   <div>
   <div>
-    <ARow>
-      <ACol :span="6">
-        <AFormItem :label="$t('createDevice.equipmentGroup')" name="deviceData" :label-col="{ span: 5 }">
+    <AFlex>
+      <div>
+        <AFormItem :label="$t('createDevice.equipmentGroup')" name="deviceData">
           <ACascader
           <ACascader
-            class="equipment-group"
+            class="equipment-type"
             v-model:value="form.deviceData"
             v-model:value="form.deviceData"
             :field-names="{ label: 'groupName', value: 'id', children: 'deviceGroupChilds' }"
             :field-names="{ label: 'groupName', value: 'id', children: 'deviceGroupChilds' }"
             :options="deviceGroup"
             :options="deviceGroup"
@@ -48,7 +48,7 @@ onMounted(() => {
             change-on-select
             change-on-select
           />
           />
         </AFormItem>
         </AFormItem>
-        <AFormItem :label="$t('setupProtocol.deviceType')" name="deviceType" :label-col="{ span: 5 }">
+        <AFormItem :label="$t('setupProtocol.deviceType')" name="deviceType">
           <ASelect
           <ASelect
             class="equipment-type"
             class="equipment-type"
             v-model:value="form.deviceType"
             v-model:value="form.deviceType"
@@ -57,26 +57,33 @@ onMounted(() => {
             :placeholder="$t('common.plzSelect')"
             :placeholder="$t('common.plzSelect')"
             @change="selectTypeRquipment"
             @change="selectTypeRquipment"
           />
           />
-          <ATooltip placement="top">
-            <template #title>
-              <span>{{ $t('createDevice.suggestion') }}</span>
-            </template>
-
-            <SvgIcon class="information-prompt" name="exclamation-circle-o" />
-          </ATooltip>
         </AFormItem>
         </AFormItem>
-        <AFormItem :label="$t('createDevice.deviceName')" name="deviceName" :label-col="{ span: 5 }">
-          <AInput class="equipment-name" v-model:value="form.deviceName" />
+        <AFormItem :label="$t('createDevice.deviceName')" name="deviceName">
+          <AFlex class="flex-width" align="center">
+            <AInput :placeholder="$t('common.pleaseEnter')" class="equipment-type" v-model:value="form.deviceName" />
+            <ATooltip placement="top">
+              <template #title>
+                <span>{{ $t('createDevice.suggestion') }}</span>
+              </template>
+              <div>
+                <SvgIcon class="information-prompt" name="exclamation-circle-o" />
+              </div>
+            </ATooltip>
+          </AFlex>
         </AFormItem>
         </AFormItem>
-      </ACol>
-      <ACol :span="18" v-if="form.deviceType">
+      </div>
+      <div>
         <img class="information-img" referrerpolicy="no-referrer" :src="imgUrl" />
         <img class="information-img" referrerpolicy="no-referrer" :src="imgUrl" />
-      </ACol>
-    </ARow>
+      </div>
+    </AFlex>
   </div>
   </div>
 </template>
 </template>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
+.flex-width {
+  width: 350px;
+}
+
 .information-prompt {
 .information-prompt {
   width: 14px;
   width: 14px;
   height: 14px;
   height: 14px;
@@ -90,15 +97,7 @@ onMounted(() => {
   height: 208px;
   height: 208px;
 }
 }
 
 
-.equipment-group {
-  width: 256px;
-}
-
 .equipment-type {
 .equipment-type {
   width: 256px;
   width: 256px;
 }
 }
-
-.equipment-name {
-  width: 256px;
-}
 </style>
 </style>

+ 16 - 14
src/views/create-device/CreateDevice.vue

@@ -1,5 +1,5 @@
 <script setup lang="ts">
 <script setup lang="ts">
-import { computed, reactive } from 'vue';
+import { computed, reactive, ref, shallowRef } from 'vue';
 
 
 import UseGuidance from '@/layout/UseGuidance.vue';
 import UseGuidance from '@/layout/UseGuidance.vue';
 import BasicInformation from '@/views/create-device/BasicInformation.vue';
 import BasicInformation from '@/views/create-device/BasicInformation.vue';
@@ -13,14 +13,14 @@ import type { EquipmentInformationForm, FormRules, RegisterGatewayForm, UseGuide
 const equipmentInformationForm = reactive<EquipmentInformationForm>({
 const equipmentInformationForm = reactive<EquipmentInformationForm>({
   groupId: 0,
   groupId: 0,
   deviceData: [],
   deviceData: [],
-  deviceType: '',
+  deviceType: undefined,
   deviceName: '',
   deviceName: '',
-  brand: 0,
-  model: 0,
-  modelType: 0,
-  controlType: 0,
-  compressionLevel: 0,
-  voltageLevel: 0,
+  brand: undefined,
+  model: undefined,
+  modelType: undefined,
+  controlType: undefined,
+  compressionLevel: undefined,
+  voltageLevel: undefined,
   powerRating: '',
   powerRating: '',
   powerUnload: '',
   powerUnload: '',
   maximumFlow: '',
   maximumFlow: '',
@@ -61,31 +61,33 @@ const rules = computed<FormRules<RegisterGatewayForm>>(() => {
   };
   };
 });
 });
 
 
-const steps: UseGuideStepItem[] = [
+const steps = ref<UseGuideStepItem[]>([
   {
   {
     title: t('createDevice.basicInformation'),
     title: t('createDevice.basicInformation'),
-    component: BasicInformation,
+    component: shallowRef(BasicInformation),
     stepDescription: '描述文本',
     stepDescription: '描述文本',
+    labelAlign: 'left',
+    labelCol: { span: 6 },
   },
   },
   {
   {
     title: t('createDevice.detailedInformation'),
     title: t('createDevice.detailedInformation'),
-    component: DetailedInformation,
+    component: shallowRef(DetailedInformation),
     stepDescription: '描述文本',
     stepDescription: '描述文本',
     formLayout: 'vertical',
     formLayout: 'vertical',
   },
   },
   {
   {
     title: t('createDevice.selectGatewayParameters'),
     title: t('createDevice.selectGatewayParameters'),
-    component: GatewayParameters,
+    component: shallowRef(GatewayParameters),
     stepDescription: '描述文本',
     stepDescription: '描述文本',
   },
   },
   {
   {
     title: t('createDevice.verifyData'),
     title: t('createDevice.verifyData'),
-    component: VerifyParameters,
+    component: shallowRef(VerifyParameters),
     stepDescription: '描述文本',
     stepDescription: '描述文本',
     nextStepButtonText: t('common.finishSetup'),
     nextStepButtonText: t('common.finishSetup'),
     isLastStep: true,
     isLastStep: true,
   },
   },
-];
+]);
 </script>
 </script>
 
 
 <template>
 <template>

+ 34 - 19
src/views/create-device/DetailedInformation.vue

@@ -1,8 +1,9 @@
 <script setup lang="ts">
 <script setup lang="ts">
-import { onMounted, ref } from 'vue';
+import { inject, onMounted, ref } from 'vue';
 
 
 import { useRequest } from '@/hooks/request';
 import { useRequest } from '@/hooks/request';
 import { deviceAdd, groupList } from '@/api';
 import { deviceAdd, groupList } from '@/api';
+import { IS_USED_IN_MODAL_GUIDANCE } from '@/constants/inject-key';
 
 
 import type {
 import type {
   EquipmentInformationForm,
   EquipmentInformationForm,
@@ -12,7 +13,7 @@ import type {
 } from '@/types';
 } from '@/types';
 
 
 const props = defineProps<UseGuideStepItemProps<EquipmentInformationForm>>();
 const props = defineProps<UseGuideStepItemProps<EquipmentInformationForm>>();
-
+const isUsedInModalGuidance = inject(IS_USED_IN_MODAL_GUIDANCE, false);
 const { handleRequest } = useRequest();
 const { handleRequest } = useRequest();
 
 
 const brandList = ref<EquipmentTypeItem[]>([]);
 const brandList = ref<EquipmentTypeItem[]>([]);
@@ -76,19 +77,30 @@ onMounted(() => {
 
 
 <template>
 <template>
   <div>
   <div>
-    <AFlex class="equipment-information" wrap="wrap" :gap="33">
+    <AFlex class="equipment-information" wrap="wrap" :gap="isUsedInModalGuidance ? 28 : 33">
       <AFormItem :label="$t('createDevice.brand')" name="brand">
       <AFormItem :label="$t('createDevice.brand')" name="brand">
-        <ASelect v-model:value="form.brand" :options="brandList" :field-names="{ label: 'dataName', value: 'id' }" />
+        <ASelect
+          :placeholder="$t('common.plzSelect')"
+          v-model:value="form.brand"
+          :options="brandList"
+          :field-names="{ label: 'dataName', value: 'id' }"
+        />
       </AFormItem>
       </AFormItem>
 
 
       <AFormItem :label="$t('createDevice.modelNumber')" name="model">
       <AFormItem :label="$t('createDevice.modelNumber')" name="model">
-        <ASelect v-model:value="form.model" :options="modelList" :field-names="{ label: 'dataName', value: 'id' }" />
+        <ASelect
+          :placeholder="$t('common.plzSelect')"
+          v-model:value="form.model"
+          :options="modelList"
+          :field-names="{ label: 'dataName', value: 'id' }"
+        />
       </AFormItem>
       </AFormItem>
 
 
       <AFormItem :label="$t('createDevice.controllerModel')" name="modelTypeList">
       <AFormItem :label="$t('createDevice.controllerModel')" name="modelTypeList">
         <ASelect
         <ASelect
           v-model:value="form.modelType"
           v-model:value="form.modelType"
           :options="modelTypeList"
           :options="modelTypeList"
+          :placeholder="$t('common.plzSelect')"
           :field-names="{ label: 'dataName', value: 'id' }"
           :field-names="{ label: 'dataName', value: 'id' }"
         />
         />
       </AFormItem>
       </AFormItem>
@@ -97,6 +109,7 @@ onMounted(() => {
         <ASelect
         <ASelect
           v-model:value="form.controlType"
           v-model:value="form.controlType"
           :options="controlTypeList"
           :options="controlTypeList"
+          :placeholder="$t('common.plzSelect')"
           :field-names="{ label: 'dataName', value: 'id' }"
           :field-names="{ label: 'dataName', value: 'id' }"
         />
         />
       </AFormItem>
       </AFormItem>
@@ -105,6 +118,7 @@ onMounted(() => {
         <ASelect
         <ASelect
           v-model:value="form.compressionLevel"
           v-model:value="form.compressionLevel"
           :options="compressionLevelList"
           :options="compressionLevelList"
+          :placeholder="$t('common.plzSelect')"
           :field-names="{ label: 'dataName', value: 'id' }"
           :field-names="{ label: 'dataName', value: 'id' }"
         />
         />
       </AFormItem>
       </AFormItem>
@@ -113,66 +127,67 @@ onMounted(() => {
         <ASelect
         <ASelect
           v-model:value="form.voltageLevel"
           v-model:value="form.voltageLevel"
           :options="voltageLevelList"
           :options="voltageLevelList"
+          :placeholder="$t('common.plzSelect')"
           :field-names="{ label: 'dataName', value: 'id' }"
           :field-names="{ label: 'dataName', value: 'id' }"
         />
         />
       </AFormItem>
       </AFormItem>
 
 
       <AFormItem :label="$t('createDevice.ratedPower')" name="powerRating">
       <AFormItem :label="$t('createDevice.ratedPower')" name="powerRating">
-        <AInputNumber v-model:value="form.powerRating" />
+        <AInputNumber :placeholder="$t('common.pleaseEnter')" v-model:value="form.powerRating" />
       </AFormItem>
       </AFormItem>
 
 
       <AFormItem :label="$t('createDevice.uninstallPower')" name="powerUnload">
       <AFormItem :label="$t('createDevice.uninstallPower')" name="powerUnload">
-        <AInputNumber v-model:value="form.powerUnload" />
+        <AInputNumber :placeholder="$t('common.pleaseEnter')" v-model:value="form.powerUnload" />
       </AFormItem>
       </AFormItem>
 
 
       <AFormItem :label="$t('createDevice.nominalVolumetric')" name="maximumFlow">
       <AFormItem :label="$t('createDevice.nominalVolumetric')" name="maximumFlow">
-        <AInputNumber v-model:value="form.maximumFlow" />
+        <AInputNumber :placeholder="$t('common.pleaseEnter')" v-model:value="form.maximumFlow" />
       </AFormItem>
       </AFormItem>
 
 
       <AFormItem :label="$t('createDevice.ratedWorkingPressure')" name="pressure">
       <AFormItem :label="$t('createDevice.ratedWorkingPressure')" name="pressure">
-        <AInputNumber v-model:value="form.pressure" />
+        <AInputNumber :placeholder="$t('common.pleaseEnter')" v-model:value="form.pressure" />
       </AFormItem>
       </AFormItem>
 
 
       <AFormItem :label="$t('createDevice.maximumWorkingPressure')" name="pressureMax">
       <AFormItem :label="$t('createDevice.maximumWorkingPressure')" name="pressureMax">
-        <AInputNumber v-model:value="form.pressureMax" />
+        <AInputNumber :placeholder="$t('common.pleaseEnter')" v-model:value="form.pressureMax" />
       </AFormItem>
       </AFormItem>
 
 
       <AFormItem :label="$t('createDevice.manufacturingDate')" name="productionDate">
       <AFormItem :label="$t('createDevice.manufacturingDate')" name="productionDate">
-        <ADatePicker v-model:value="form.productionDate">
+        <ADatePicker :placeholder="$t('common.pleaseEnter')" v-model:value="form.productionDate">
           <template #suffixIcon> </template>
           <template #suffixIcon> </template>
         </ADatePicker>
         </ADatePicker>
       </AFormItem>
       </AFormItem>
 
 
       <AFormItem :label="$t('createDevice.factorySerialNumber')" name="productionNum">
       <AFormItem :label="$t('createDevice.factorySerialNumber')" name="productionNum">
-        <AInput v-model:value="form.productionNum" />
+        <AInput :placeholder="$t('common.pleaseEnter')" v-model:value="form.productionNum" />
       </AFormItem>
       </AFormItem>
 
 
       <AFormItem :label="$t('createDevice.equipmentNumber')" name="deviceNum">
       <AFormItem :label="$t('createDevice.equipmentNumber')" name="deviceNum">
-        <AInput v-model:value="form.deviceNum" />
+        <AInput :placeholder="$t('common.pleaseEnter')" v-model:value="form.deviceNum" />
       </AFormItem>
       </AFormItem>
 
 
       <AFormItem :label="$t('createDevice.mainTechnicalParameters')" name="mainTechData">
       <AFormItem :label="$t('createDevice.mainTechnicalParameters')" name="mainTechData">
-        <AInput v-model:value="form.mainTechData" />
+        <AInput :placeholder="$t('common.pleaseEnter')" v-model:value="form.mainTechData" />
       </AFormItem>
       </AFormItem>
 
 
       <AFormItem :label="$t('createDevice.installationLocation')" name="mountedPosition">
       <AFormItem :label="$t('createDevice.installationLocation')" name="mountedPosition">
-        <AInput v-model:value="form.mountedPosition" />
+        <AInput :placeholder="$t('common.pleaseEnter')" v-model:value="form.mountedPosition" />
       </AFormItem>
       </AFormItem>
 
 
       <AFormItem :label="$t('createDevice.usingDepartment')" name="department">
       <AFormItem :label="$t('createDevice.usingDepartment')" name="department">
-        <AInput v-model:value="form.department" />
+        <AInput :placeholder="$t('common.pleaseEnter')" v-model:value="form.department" />
       </AFormItem>
       </AFormItem>
 
 
       <AFormItem :label="$t('createDevice.responsiblePerson')" name="respPerson">
       <AFormItem :label="$t('createDevice.responsiblePerson')" name="respPerson">
-        <AInput v-model:value="form.respPerson" />
+        <AInput :placeholder="$t('common.pleaseEnter')" v-model:value="form.respPerson" />
       </AFormItem>
       </AFormItem>
 
 
       <AFormItem :label="$t('createDevice.contactNumber')" name="phone">
       <AFormItem :label="$t('createDevice.contactNumber')" name="phone">
-        <AInput v-model:value="form.phone" />
+        <AInput :placeholder="$t('common.pleaseEnter')" v-model:value="form.phone" />
       </AFormItem>
       </AFormItem>
 
 
       <AFormItem :label="$t('createDevice.serviceLife')" name="serviceLife">
       <AFormItem :label="$t('createDevice.serviceLife')" name="serviceLife">
-        <AInput v-model:value="form.serviceLife" />
+        <AInput :placeholder="$t('common.pleaseEnter')" v-model:value="form.serviceLife" />
       </AFormItem>
       </AFormItem>
     </AFlex>
     </AFlex>
     <AFormItem :label="$t('common.note')" name="remarks">
     <AFormItem :label="$t('common.note')" name="remarks">

+ 149 - 46
src/views/create-device/GatewayParameters.vue

@@ -1,7 +1,8 @@
 <script setup lang="ts">
 <script setup lang="ts">
-import { onMounted, ref } from 'vue';
+import { onMounted, ref, useTemplateRef } from 'vue';
 import { message } from 'ant-design-vue';
 import { message } from 'ant-design-vue';
 
 
+import ConfirmModal from '@/components/ConfirmModal.vue';
 import SvgIcon from '@/components/SvgIcon.vue';
 import SvgIcon from '@/components/SvgIcon.vue';
 import { useRequest } from '@/hooks/request';
 import { useRequest } from '@/hooks/request';
 import { t } from '@/i18n';
 import { t } from '@/i18n';
@@ -170,7 +171,7 @@ const customizationColumns = [
 
 
 const protocolEquipmentColumns = [
 const protocolEquipmentColumns = [
   {
   {
-    title: t('common.sequenceNumber'),
+    title: t('common.serialNumber'),
     dataIndex: 'index',
     dataIndex: 'index',
     key: 'index',
     key: 'index',
     ellipsis: true,
     ellipsis: true,
@@ -215,6 +216,10 @@ interface GatewayList {
   linkLists: PhysicalInterfaceList[];
   linkLists: PhysicalInterfaceList[];
 }
 }
 
 
+const modalGatewayRef = useTemplateRef('modalGateway');
+const modalEquipmentRef = useTemplateRef('modalEquipment');
+const modalCustomizationRef = useTemplateRef('modalCustomization');
+
 const props = defineProps<UseGuideStepItemProps<EquipmentInformationForm>>();
 const props = defineProps<UseGuideStepItemProps<EquipmentInformationForm>>();
 const gatewayList = ref<GatewayList[]>([]);
 const gatewayList = ref<GatewayList[]>([]);
 const monitorAssociationGatewayList = ref<ListEquipmentParametersItem[]>([]);
 const monitorAssociationGatewayList = ref<ListEquipmentParametersItem[]>([]);
@@ -249,6 +254,9 @@ const controlEquipmentLsit = ref<Key[]>([]);
 const open = ref<boolean>(false);
 const open = ref<boolean>(false);
 const open1 = ref<boolean>(false);
 const open1 = ref<boolean>(false);
 const open2 = ref<boolean>(false);
 const open2 = ref<boolean>(false);
+const gatewayIndex = ref<number>(0);
+const equipmentIndex = ref<number>(0);
+const customizationIndex = ref<number>(0);
 
 
 let gatewayId: number;
 let gatewayId: number;
 
 
@@ -287,6 +295,15 @@ const selectParameters = (value: number, id: number) => {
   }
   }
 };
 };
 
 
+const queryReset = (value: string) => {
+  if (value === 'monitor') {
+    monitorSearchContent.value = '';
+  } else if (value === 'control') {
+    controlSearchContent.value = '';
+  }
+  fuzzyQuery(value);
+};
+
 const fuzzyQuery = (value: string) => {
 const fuzzyQuery = (value: string) => {
   if (value === 'monitor') {
   if (value === 'monitor') {
     listEquipmentParameters.value = listAllEquipmentParameters.value.filter((item) =>
     listEquipmentParameters.value = listAllEquipmentParameters.value.filter((item) =>
@@ -362,25 +379,20 @@ const postGatewayLinkProtocolList = (linkId: number, id: number, monitorType: st
 };
 };
 
 
 const gatewayDelete = (divId: number, linkDeleteId: number, index: number) => {
 const gatewayDelete = (divId: number, linkDeleteId: number, index: number) => {
-  gatewayList.value.splice(index, 1);
-  monitorAssociationGatewayList.value = monitorAssociationGatewayList.value.filter(
-    (item) => item.gatewayId === divId && item.linkId !== linkDeleteId,
-  );
-  controlAssociationGatewayList.value = controlAssociationGatewayList.value.filter(
-    (item) => item.gatewayId === divId && item.linkId !== linkDeleteId,
-  );
+  modalGatewayRef.value?.showView();
+  gatewayIndex.value = index;
+  gatewayId = divId;
+  linkId = linkDeleteId;
 };
 };
 
 
 const customizationDelete = (index: number) => {
 const customizationDelete = (index: number) => {
-  customizationData.value.splice(index, 1);
+  modalCustomizationRef.value?.showView();
+  customizationIndex.value = index;
 };
 };
 
 
 const gatewayDevDelete = (index: number) => {
 const gatewayDevDelete = (index: number) => {
-  if (agreementListKey.value === 'monitoring') {
-    monitorAssociationGatewayList.value.splice(index, 1);
-  } else {
-    controlAssociationGatewayList.value.splice(index, 1);
-  }
+  modalEquipmentRef.value?.showView();
+  equipmentIndex.value = index;
 };
 };
 
 
 const handleOk = () => {
 const handleOk = () => {
@@ -512,6 +524,7 @@ const serialNumberAdd = (value: SelectValue, option: DefaultOptionType, index: n
 
 
   gatewayList.value[index].links = links;
   gatewayList.value[index].links = links;
   gatewayList.value[index].linkLists = links;
   gatewayList.value[index].linkLists = links;
+  gatewayList.value[index].linkName = '';
 };
 };
 
 
 const obtainParamValueListAutomatic = (linkId: number) => {
 const obtainParamValueListAutomatic = (linkId: number) => {
@@ -531,6 +544,20 @@ const linkSwitch = (value: SelectValue, option: DefaultOptionType, index: number
   gatewayId = divId;
   gatewayId = divId;
   gatewayList.value[index].linkId = option.linkId;
   gatewayList.value[index].linkId = option.linkId;
   gatewayList.value[index].modelNameShow = false;
   gatewayList.value[index].modelNameShow = false;
+
+  // 创建gatewayList的键集合
+  const bKeys = new Set(gatewayList.value.map((item) => `${item.divId},${item.linkId}`));
+
+  // 过滤数组
+  const monitor = monitorAssociationGatewayList.value.filter((item) => bKeys.has(`${item.gatewayId},${item.linkId}`));
+
+  monitorAssociationGatewayList.value = monitor;
+
+  // 过滤数组
+  const control = controlAssociationGatewayList.value.filter((item) => bKeys.has(`${item.gatewayId},${item.linkId}`));
+
+  controlAssociationGatewayList.value = control;
+
   obtainParamValueListAutomatic(option.linkId);
   obtainParamValueListAutomatic(option.linkId);
 };
 };
 
 
@@ -618,7 +645,7 @@ const arrayIdFiltering = (a: Key[], b: ListEquipmentParametersItem[]) => {
 const validateParams = () => {
 const validateParams = () => {
   const errors: string[] = [];
   const errors: string[] = [];
   const codes = new Set<string>();
   const codes = new Set<string>();
-  const names = new Set<string>();
+
   const dataList = [
   const dataList = [
     ...monitorAssociationGatewayList.value,
     ...monitorAssociationGatewayList.value,
     ...controlAssociationGatewayList.value,
     ...controlAssociationGatewayList.value,
@@ -629,11 +656,8 @@ const validateParams = () => {
     if (codes.has(param.deviceParamCode)) {
     if (codes.has(param.deviceParamCode)) {
       errors.push(`设备参数编码:" ${param.deviceParamCode} "重复`);
       errors.push(`设备参数编码:" ${param.deviceParamCode} "重复`);
     }
     }
-    if (names.has(param.deviceParamName)) {
-      errors.push(`设备参数名称:" ${param.deviceParamName} "重复`);
-    }
+
     codes.add(param.deviceParamCode);
     codes.add(param.deviceParamCode);
-    names.add(param.deviceParamName);
   });
   });
 
 
   return errors;
   return errors;
@@ -645,16 +669,19 @@ const finish = async () => {
     ...controlAssociationGatewayList.value,
     ...controlAssociationGatewayList.value,
     ...customizationData.value,
     ...customizationData.value,
   ];
   ];
+  if (gatewayList.value.some((item) => item.linkName == '')) {
+    throw new Error('物理接口不能为空!');
+  }
 
 
+  if ([...monitorAssociationGatewayList.value, ...controlAssociationGatewayList.value].length === 0) {
+    throw new Error('配置设备参数不能为空!');
+  }
   if (dataList.some((item) => item.deviceParamCode == '')) {
   if (dataList.some((item) => item.deviceParamCode == '')) {
     throw new Error('设备参数编码不能为空!');
     throw new Error('设备参数编码不能为空!');
   }
   }
-  if (dataList.some((item) => item.deviceParamName == '')) {
-    throw new Error('设备参数名称不能为空!');
-  }
   const valueList = validateParams();
   const valueList = validateParams();
   if (valueList.length) {
   if (valueList.length) {
-    throw new Error('设备参数名称或设备参数编码存在重复项!');
+    throw new Error('设备参数编码存在重复项!');
   }
   }
 
 
   deviceParamGroups.value = [];
   deviceParamGroups.value = [];
@@ -806,7 +833,31 @@ const addAutomaticMatching = () => {
   open2.value = false;
   open2.value = false;
 };
 };
 
 
-const openChange = () => {};
+const confirmGateway = () => {
+  gatewayList.value.splice(gatewayIndex.value, 1);
+  monitorAssociationGatewayList.value = monitorAssociationGatewayList.value.filter(
+    (item) => !(item.gatewayId === gatewayId && item.linkId === linkId),
+  );
+  controlAssociationGatewayList.value = controlAssociationGatewayList.value.filter(
+    (item) => !(item.gatewayId === gatewayId && item.linkId === linkId),
+  );
+  modalGatewayRef.value?.hideView();
+};
+
+const confirmEquipment = () => {
+  if (agreementListKey.value === 'monitoring') {
+    monitorAssociationGatewayList.value.splice(equipmentIndex.value, 1);
+  } else {
+    controlAssociationGatewayList.value.splice(equipmentIndex.value, 1);
+  }
+
+  modalEquipmentRef.value?.hideView();
+};
+
+const confirmCustomization = () => {
+  customizationData.value.splice(customizationIndex.value, 1);
+  modalCustomizationRef.value?.hideView();
+};
 
 
 onMounted(() => {
 onMounted(() => {
   handleRequest(async () => {
   handleRequest(async () => {
@@ -1092,7 +1143,7 @@ onMounted(() => {
             {{ index + 1 }}
             {{ index + 1 }}
           </template>
           </template>
           <template v-else-if="column.key === 'deviceParamCode'">
           <template v-else-if="column.key === 'deviceParamCode'">
-            <ATooltip :destroy-tooltip-on-hide="true" @openChange="openChange">
+            <ATooltip :destroy-tooltip-on-hide="true">
               <template #title>{{ record.deviceParamCode }}</template>
               <template #title>{{ record.deviceParamCode }}</template>
             </ATooltip>
             </ATooltip>
             <AInput
             <AInput
@@ -1181,16 +1232,25 @@ onMounted(() => {
           <div class="gateway-parameters-left">
           <div class="gateway-parameters-left">
             <ATabs v-model:active-key="agreementKey">
             <ATabs v-model:active-key="agreementKey">
               <ATabPane key="monitoring" :tab="$t('createDevice.dataMonitoring')">
               <ATabPane key="monitoring" :tab="$t('createDevice.dataMonitoring')">
-                <AInput
-                  :placeholder="$t('common.search')"
-                  v-model:value="monitorSearchContent"
-                  class="gateway-parameters-left-bottom"
-                  allow-clear
-                >
-                  <template #prefix>
-                    <SvgIcon class="search-svg" @click="fuzzyQuery('monitor')" name="search-o" />
-                  </template>
-                </AInput>
+                <AFlex justify="space-between" align="center" class="gateway-parameters-left-bottom">
+                  <AInput
+                    placeholder="清输入网关参数名称搜索"
+                    v-model:value="monitorSearchContent"
+                    class="input-width"
+                    allow-clear
+                  >
+                    <template #prefix>
+                      <SvgIcon class="search-svg" name="search-o" />
+                    </template>
+                  </AInput>
+                  <div>
+                    <AButton class="button-margin" type="primary" @click="fuzzyQuery('monitor')">
+                      {{ $t('common.query') }}
+                    </AButton>
+                    <AButton type="primary" ghost @click="queryReset('monitor')">{{ $t('common.reset') }}</AButton>
+                  </div>
+                </AFlex>
+
                 <ATable
                 <ATable
                   :row-selection="{
                   :row-selection="{
                     type: 'checkbox',
                     type: 'checkbox',
@@ -1211,16 +1271,26 @@ onMounted(() => {
                 </ATable>
                 </ATable>
               </ATabPane>
               </ATabPane>
               <ATabPane key="remote" :tab="$t('createDevice.remoteControl')" force-render>
               <ATabPane key="remote" :tab="$t('createDevice.remoteControl')" force-render>
-                <AInput
-                  :placeholder="$t('common.search')"
-                  v-model:value="controlSearchContent"
-                  class="gateway-parameters-left-bottom"
-                  allow-clear
-                >
-                  <template #prefix>
-                    <SvgIcon class="search-svg" @click="fuzzyQuery('control')" name="search-o" />
-                  </template>
-                </AInput>
+                <AFlex justify="space-between" align="center" class="gateway-parameters-left-bottom">
+                  <AInput
+                    placeholder="清输入网关参数名称搜索"
+                    class="input-width"
+                    v-model:value="controlSearchContent"
+                    allow-clear
+                  >
+                    <template #prefix>
+                      <SvgIcon class="search-svg" name="search-o" />
+                    </template>
+                  </AInput>
+
+                  <div>
+                    <AButton class="button-margin" type="primary" @click="fuzzyQuery('control')">
+                      {{ $t('common.query') }}
+                    </AButton>
+                    <AButton type="primary" ghost @click="queryReset('control')">{{ $t('common.reset') }}</AButton>
+                  </div>
+                </AFlex>
+
                 <ATable
                 <ATable
                   :row-selection="{
                   :row-selection="{
                     type: 'checkbox',
                     type: 'checkbox',
@@ -1352,10 +1422,39 @@ onMounted(() => {
       </template>
       </template>
       <div class="description">{{ $t('createDevice.matchParameters') }}</div>
       <div class="description">{{ $t('createDevice.matchParameters') }}</div>
     </AModal>
     </AModal>
+
+    <ConfirmModal
+      ref="modalGateway"
+      :title="$t('common.deleteConfirmation')"
+      :description-text="$t('common.confirmDeletion')"
+      :icon="{ name: 'delete' }"
+      :icon-bg-color="'#F56C6C'"
+      @confirm="confirmGateway"
+    />
+    <ConfirmModal
+      ref="modalEquipment"
+      :title="$t('common.deleteConfirmation')"
+      :description-text="$t('common.confirmDeletion')"
+      :icon="{ name: 'delete' }"
+      :icon-bg-color="'#F56C6C'"
+      @confirm="confirmEquipment"
+    />
+    <ConfirmModal
+      ref="modalCustomization"
+      :title="$t('common.deleteConfirmation')"
+      :description-text="$t('common.confirmDeletion')"
+      :icon="{ name: 'delete' }"
+      :icon-bg-color="'#F56C6C'"
+      @confirm="confirmCustomization"
+    />
   </div>
   </div>
 </template>
 </template>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
+.button-margin {
+  margin-right: 12px;
+}
+
 .footer-div-top {
 .footer-div-top {
   margin-top: 24px;
   margin-top: 24px;
 }
 }
@@ -1377,6 +1476,10 @@ onMounted(() => {
   padding-bottom: 24px;
   padding-bottom: 24px;
 }
 }
 
 
+.input-width {
+  width: 256px;
+}
+
 .gateway-parameters-left-bottom {
 .gateway-parameters-left-bottom {
   margin-bottom: 16px;
   margin-bottom: 16px;
 }
 }