Procházet zdrojové kódy

perf(views): 优化 “绑定协议”步骤

1.重构部分UI布局与现实
2.删除从站列表支持对话框交互
3更换协议列表支持重置按钮
4.绑定协议-根据协议类型展示不同协议配置项
wangshun před 1 měsícem
rodič
revize
679bc9cf84
1 změnil soubory, kde provedl 217 přidání a 111 odebrání
  1. 217 111
      src/views/register-gateway/BindProtocol.vue

+ 217 - 111
src/views/register-gateway/BindProtocol.vue

@@ -15,7 +15,7 @@ import {
   getDictTypeData,
   postProtocolCandidatesList,
 } from '@/api';
-import { DictCode } from '@/constants';
+import { DictCode, ProtocolType } from '@/constants';
 
 import type { FormInstance } from 'ant-design-vue';
 import type { Rule } from 'ant-design-vue/es/form';
@@ -38,9 +38,8 @@ const { handleRequest } = useRequest();
 const props = defineProps<UseGuideStepItemProps<RegisterGatewayForm>>();
 
 const interfaceData = ref<InterfaceData[]>([]);
-const agreementKey = ref<string>('own');
 
-const agreementForm = reactive<AgreementForm>({
+const agreementForm = ref<AgreementForm>({
   baudRate: 0,
   dataBit: '',
   parityBit: '',
@@ -53,11 +52,11 @@ const agreementForm = reactive<AgreementForm>({
 const open = ref<boolean>(false);
 const open1 = ref<boolean>(false);
 const open2 = ref<boolean>(false);
-
+const isModbusRtuProtocol = ref<boolean>(false);
 const agreementData = ref<AgreementData[]>([]);
 
 const baudRatelist = ref<OptionItem<number>[]>([]);
-
+const slaveStationIndex = ref<number>(0);
 const protocolList = ref<ProtocolItem[]>([]);
 const protocolQuery = ref<ProtocolList>({
   pageIndex: 1,
@@ -68,15 +67,15 @@ const protocolQuery = ref<ProtocolList>({
 const protocolTotal = ref<number>(0);
 
 const formRef = ref<FormInstance>();
-
+const formSettingsRef = ref<FormInstance>();
 const protocolsItem = reactive<AgreementData>({
   protocolType: '',
   station: '',
   name: '',
   protocolName: '',
   deviceName: '',
-  dataSendInterval: 0,
-  highFreqSendInterval: 0,
+  dataSendInterval: 1,
+  highFreqSendInterval: 1,
   protocolId: 0,
   isStandard: '0',
 });
@@ -91,6 +90,7 @@ let advancedIndex: number;
 
 let verificationAgreement: VerificationAgreement[] = [];
 
+const modalInterfaceComponentRef = useTemplateRef('modalInterfaceComponent');
 const modalComponentRef = useTemplateRef('modalComponent');
 
 let data: ProtocolsItem[] = [];
@@ -101,31 +101,31 @@ const columns = [
     dataIndex: 'protocolType',
     key: 'protocolType',
     ellipsis: true,
+    width: 160,
   },
-  {
-    title: t('registerGateway.fromStationNumber'),
-    dataIndex: 'station',
-    key: 'station',
-    ellipsis: true,
-  },
-  {
-    title: t('registerGateway.electricMeter'),
-    dataIndex: 'name',
-    key: 'name',
-    ellipsis: true,
-  },
+  // {
+  //   title: t('registerGateway.fromStationNumber'),
+  //   dataIndex: 'station',
+  //   key: 'station',
+  //   ellipsis: true,
+  // },
+  // {
+  //   title: t('registerGateway.electricMeter'),
+  //   dataIndex: 'name',
+  //   key: 'name',
+  //   ellipsis: true,
+  // },
   {
     title: t('registerGateway.communicationProtocol'),
     key: 'protocolName',
     dataIndex: 'protocolName',
-    width: 240,
-  },
-  {
-    title: t('registerGateway.associatedEquipment'),
-    key: 'deviceName',
-    dataIndex: 'deviceName',
-    ellipsis: true,
   },
+  // {
+  //   title: t('registerGateway.associatedEquipment'),
+  //   key: 'deviceName',
+  //   dataIndex: 'deviceName',
+  //   ellipsis: true,
+  // },
   {
     title: t('common.operation'),
     key: 'action',
@@ -135,9 +135,9 @@ const columns = [
 
 const protocolColumns = [
   {
-    title: t('setupProtocol.protocolType'),
-    dataIndex: 'protocolName',
-    key: 'protocolName',
+    title: t('setupProtocol.deviceType'),
+    dataIndex: 'deviceType',
+    key: 'deviceType',
   },
   {
     title: t('registerGateway.agreementNumber'),
@@ -146,8 +146,8 @@ const protocolColumns = [
   },
   {
     title: t('setupProtocol.protocolName'),
-    dataIndex: 'deviceType',
-    key: 'deviceType',
+    dataIndex: 'protocolName',
+    key: 'protocolName',
   },
 ];
 
@@ -157,17 +157,22 @@ const postGetList = () => {
   });
 };
 
-const confirm = () => {
+const confirmInterface = () => {
   handleRequest(async () => {
     await gatewayLinkDelete(agreementId);
     postGetList();
   });
+  modalInterfaceComponentRef.value?.hideView();
+};
+
+const confirm = () => {
+  agreementData.value.splice(slaveStationIndex.value, 1);
   modalComponentRef.value?.hideView();
 };
 
 const addDelete = (value: number) => {
   agreementId = value;
-  modalComponentRef.value?.showView();
+  modalInterfaceComponentRef.value?.showView();
 };
 
 const addSlave = () => {
@@ -177,13 +182,17 @@ const addSlave = () => {
     name: '',
     protocolName: '',
     deviceName: '',
-    dataSendInterval: 0,
-    highFreqSendInterval: 0,
+    dataSendInterval: 1,
+    highFreqSendInterval: 1,
     protocolId: undefined,
     isStandard: '0',
   });
 };
 
+const offAgreement = () => {
+  open.value = false;
+};
+
 const bindingAgreement = () => {
   data = [];
   formRef.value
@@ -193,6 +202,16 @@ const bindingAgreement = () => {
         return message.warning(t('registerGateway.prompt'));
       }
 
+      if (agreementData.value.some((item) => item.protocolId == undefined)) {
+        return message.warning(t('registerGateway.pleaseCommunicationProtocol'));
+      }
+
+      // const hasDuplicates =
+      //   new Set(agreementData.value.map((item) => item.station)).size !== agreementData.value.length;
+      // if (hasDuplicates) {
+      //   return message.warning(t('registerGateway.repeatStation'));
+      // }
+
       handleRequest(async () => {
         agreementData.value.forEach((item) => {
           const { protocolId, station, isStandard, dataSendInterval, highFreqSendInterval } = item;
@@ -212,7 +231,7 @@ const bindingAgreement = () => {
 
         const { linkName, interfaceId, gatewayId, bindState } = interfaceData.value[interfaceIndex];
         const { dataBit, parityBit, stopBit, baudRate, readTimeout, nextDataReadDelay, nextRoundDataReadDelay } =
-          agreementForm;
+          agreementForm.value;
 
         await gatewayLinkUpdate({
           id: agreementId,
@@ -238,7 +257,8 @@ const bindingAgreement = () => {
 };
 
 const deleteAgreement = (value: number) => {
-  agreementData.value.splice(value, 1);
+  modalComponentRef.value?.showView();
+  slaveStationIndex.value = value;
 };
 
 const advancedSettings = (value: AgreementData, index: number) => {
@@ -252,7 +272,10 @@ const advancedSettings = (value: AgreementData, index: number) => {
 const replaceAgreement = (value: number) => {
   agreementIndex = value;
   open1.value = true;
+  getProtocolCandidatesList();
+};
 
+const getProtocolCandidatesList = () => {
   handleRequest(async () => {
     const { records, total } = await postProtocolCandidatesList(protocolQuery.value, props.form.id);
     protocolTotal.value = total;
@@ -260,11 +283,20 @@ const replaceAgreement = (value: number) => {
   });
 };
 
+const agreementReset = () => {
+  protocolQuery.value = {
+    pageIndex: 1,
+    pageSize: 10,
+    searchContent: '',
+  };
+  getProtocolCandidatesList();
+};
+
 const agreementQuery = () => {
-  replaceAgreement(agreementIndex);
+  getProtocolCandidatesList();
 };
 const switchPages = () => {
-  replaceAgreement(agreementIndex);
+  getProtocolCandidatesList();
 };
 
 const rules1: Record<string, Rule[]> = {
@@ -292,11 +324,22 @@ const interfaceShow = (value: string) => {
 };
 
 // 显示绑定/编辑弹框
-const addEditor = (value: number, index: number, bindState: number) => {
+const addEditor = (value: number, index: number, bindState: number, protocolType: string) => {
+  agreementForm.value = {
+    baudRate: 0,
+    dataBit: '',
+    parityBit: '',
+    stopBit: '',
+    readTimeout: 0,
+    nextDataReadDelay: 0,
+    nextRoundDataReadDelay: 0,
+  };
   agreementId = value;
+  isModbusRtuProtocol.value = protocolType.includes(ProtocolType.ModbusRTU);
+
   interfaceIndex = index;
   open.value = true;
-  Object.assign(agreementForm, interfaceData.value[index]);
+  Object.assign(agreementForm.value, interfaceData.value[index]);
   agreementData.value = [];
   handleRequest(async () => {
     const data = await getDictTypeData({
@@ -308,7 +351,7 @@ const addEditor = (value: number, index: number, bindState: number) => {
         value: item.dictValueId,
         label: item.dictValue,
       }));
-      agreementForm.baudRate = Number(data[0].dictTypeDataList[0].dictValue);
+      agreementForm.value.baudRate = Number(data[0].dictTypeDataList[0].dictValue);
     }
 
     if (bindState === 1) {
@@ -342,13 +385,21 @@ const addEditor = (value: number, index: number, bindState: number) => {
 };
 
 const handleOk = () => {
-  agreementData.value[advancedIndex].dataSendInterval = protocolsItem.dataSendInterval;
-  agreementData.value[advancedIndex].highFreqSendInterval = protocolsItem.highFreqSendInterval;
-  open2.value = false;
+  formSettingsRef.value
+    ?.validate()
+    .then(() => {
+      agreementData.value[advancedIndex].dataSendInterval = protocolsItem.dataSendInterval;
+      agreementData.value[advancedIndex].highFreqSendInterval = protocolsItem.highFreqSendInterval;
+      open2.value = false;
+    })
+    .catch(() => {});
 };
 
 const handleOk1 = () => {
   if (protocolItem) {
+    if (agreementData.value.some((item) => item.protocolId === protocolItem.id)) {
+      return message.warning(t('registerGateway.cannotAddAgain'));
+    }
     const { protocolName, dataSendInterval, highFreqSendInterval, id, protocolType } = protocolItem;
     agreementData.value[agreementIndex] = {
       protocolType,
@@ -401,7 +452,7 @@ onMounted(() => {
             </AFlex>
           </ABadge>
 
-          <div @click="addEditor(item.id, index, item.bindState)">
+          <div @click="addEditor(item.id, index, item.bindState, item.protocolType)">
             <AFlex class="interface-but" justify="center" align="center">
               <SvgIcon v-if="item.bindState" class="interface-but-color" name="edit-o" />
               <SvgIcon v-else class="interface-but-color" name="binding-o" />
@@ -433,7 +484,7 @@ onMounted(() => {
         :rules="rules"
         :wrapper-col="{ span: 21 }"
       >
-        <ARow>
+        <ARow v-if="isModbusRtuProtocol">
           <ACol :span="6">
             <AFormItem :label="$t('setupProtocol.baudRate')" name="baudRate">
               <ASelect
@@ -505,26 +556,34 @@ onMounted(() => {
           <template v-if="column.key === 'protocolType'">
             <AInput disabled v-model:value="record.protocolType" />
           </template>
-          <template v-else-if="column.key === 'station'">
+          <!-- <template v-else-if="column.key === 'station'">
             <AInputNumber v-model:value="record.station" :min="1" />
-          </template>
-          <template v-else-if="column.key === 'name'">
+          </template> -->
+          <!-- <template v-else-if="column.key === 'name'">
             <AInput disabled v-model:value="record.name" />
-          </template>
+          </template> -->
           <template v-else-if="column.key === 'protocolName'">
-            <AInputSearch disabled v-model:value="record.protocolName">
+            <AFlex justify="space-between" align="center" class="protocol-name">
+              <div class="protocol-text">{{ record.protocolName }}</div>
+              <div @click="replaceAgreement(index)">
+                <AFlex justify="center" align="center" class="agreement-button">
+                  {{ $t('registerGateway.renegotiationAgreement') }}
+                </AFlex>
+              </div>
+            </AFlex>
+            <!-- <AInputSearch disabled v-model:value="record.protocolName">
               <template #enterButton>
                 <AButton class="button-color" @click="replaceAgreement(index)">{{
                   $t('registerGateway.renegotiationAgreement')
                 }}</AButton>
               </template>
-            </AInputSearch>
+            </AInputSearch> -->
           </template>
-          <template v-else-if="column.key === 'deviceName'">
+          <!-- <template v-else-if="column.key === 'deviceName'">
             <AFlex justify="center" align="center" class="device-name-tag">
               {{ record.deviceName }}
             </AFlex>
-          </template>
+          </template> -->
 
           <template v-else-if="column.key === 'action'">
             <SvgIcon
@@ -544,7 +603,7 @@ onMounted(() => {
         </AButton>
 
         <div class="footer-margin">
-          <AButton class="off-but" @click="open = false">{{ $t('common.turnOff') }}</AButton>
+          <AButton class="off-but" @click="offAgreement">{{ $t('common.turnOff') }}</AButton>
           <AButton class="off-but-width" type="primary" @click="bindingAgreement">{{ $t('common.save') }}</AButton>
         </div>
       </AFlex>
@@ -560,55 +619,42 @@ onMounted(() => {
       :mask-closable="false"
       :keyboard="false"
     >
-      <ATabs v-model:active-key="agreementKey">
-        <ATabPane key="platform" :tab="$t('registerGateway.platformAgreement')">
-          <ATable
-            :row-selection="{
-              type: 'radio',
-              onChange: rowSelectedChange,
-            }"
-            row-key="id"
-            :columns="protocolColumns"
-          />
-        </ATabPane>
-        <ATabPane key="own" :tab="$t('registerGateway.proprietaryProtocol')">
-          <ATable
-            :row-selection="{
-              type: 'radio',
-              onChange: rowSelectedChange,
-            }"
-            row-key="id"
-            :columns="protocolColumns"
-            :data-source="protocolList"
-            :pagination="false"
-          />
-          <AFlex justify="flex-end" class="footer-pagination">
-            <APagination
-              v-model:current="protocolQuery.pageIndex"
-              v-model:page-size="protocolQuery.pageSize"
-              :total="protocolTotal"
-              :show-size-changer="true"
-              @change="switchPages"
-              show-quick-jumper
-              :show-total="(total) => $t('common.pageTotal', { total })"
-            />
-          </AFlex>
-        </ATabPane>
-        <template #rightExtra>
-          <AFlex justify="flex-end">
-            <AInput
-              v-model:value="protocolQuery.searchContent"
-              class="own-input"
-              :placeholder="$t('registerGateway.pleaseProtocolName')"
-              allow-clear
-            >
-              <template #prefix>
-                <SvgIcon class="search-svg" @click="agreementQuery" name="search-o" />
-              </template>
-            </AInput>
-          </AFlex>
-        </template>
-      </ATabs>
+      <AFlex class="flex-query">
+        <AInput
+          v-model:value="protocolQuery.searchContent"
+          class="own-input"
+          :placeholder="$t('registerGateway.pleaseProtocolName')"
+          allow-clear
+        >
+          <template #prefix>
+            <SvgIcon class="search-svg" name="search-o" />
+          </template>
+        </AInput>
+
+        <AButton class="button-margin" type="primary" @click="agreementQuery"> {{ $t('common.query') }} </AButton>
+        <AButton @click="agreementReset">{{ $t('common.reset') }}</AButton>
+      </AFlex>
+      <ATable
+        :row-selection="{
+          type: 'radio',
+          onChange: rowSelectedChange,
+        }"
+        row-key="id"
+        :columns="protocolColumns"
+        :data-source="protocolList"
+        :pagination="false"
+      />
+      <AFlex justify="flex-end" class="footer-pagination">
+        <APagination
+          v-model:current="protocolQuery.pageIndex"
+          v-model:page-size="protocolQuery.pageSize"
+          :total="protocolTotal"
+          :show-size-changer="true"
+          @change="switchPages"
+          show-quick-jumper
+          :show-total="(total) => $t('common.pageTotal', { total })"
+        />
+      </AFlex>
     </AModal>
 
     <AModal
@@ -621,28 +667,89 @@ onMounted(() => {
       :mask-closable="false"
       :keyboard="false"
     >
-      <AForm :model="protocolsItem" layout="vertical" :rules="rules1">
+      <AForm ref="formSettingsRef" :model="protocolsItem" layout="vertical" :rules="rules1">
         <AFormItem :label="$t('registerGateway.dataReportingFrequency')" name="dataSendInterval">
-          <AInput v-model:value="protocolsItem.dataSendInterval" placeholder="Basic usage" />
+          <AInputNumber
+            v-model:value="protocolsItem.dataSendInterval"
+            :placeholder="t('common.pleaseEnter')"
+            :min="1"
+            :max="255"
+            style="width: 100%"
+          />
         </AFormItem>
         <AFormItem :label="$t('registerGateway.highDataFrequencyReportingFrequency')" name="highFreqSendInterval">
-          <AInput v-model:value="protocolsItem.highFreqSendInterval" placeholder="Basic usage" />
+          <AInputNumber
+            v-model:value="protocolsItem.highFreqSendInterval"
+            :placeholder="t('common.pleaseEnter')"
+            :min="1"
+            :max="255"
+            style="width: 100%"
+          />
         </AFormItem>
       </AForm>
     </AModal>
 
     <ConfirmModal
-      ref="modalComponent"
+      ref="modalInterfaceComponent"
       :title="$t('common.deleteConfirmation')"
       :description-text="$t('registerGateway.deleteInterface')"
       :icon="{ name: 'delete' }"
       :icon-bg-color="'#F56C6C'"
+      @confirm="confirmInterface"
+    />
+
+    <ConfirmModal
+      ref="modalComponent"
+      :title="$t('common.deleteConfirmation')"
+      :description-text="$t('common.confirmDeletion')"
+      :icon="{ name: 'delete' }"
+      :icon-bg-color="'#F56C6C'"
       @confirm="confirm"
     />
   </div>
 </template>
 
 <style lang="scss" scoped>
+.protocol-text {
+  width: calc(100% - 72px);
+  margin-left: 12px;
+  overflow: hidden;
+  font-size: 14px;
+  font-style: normal;
+  font-weight: 400;
+  line-height: 22px;
+  color: #333;
+  text-align: left;
+  white-space: nowrap;
+}
+
+.agreement-button {
+  width: 72px;
+  font-size: 14px;
+  font-style: normal;
+  font-weight: 400;
+  line-height: 22px;
+  color: var(--antd-color-primary-hover);
+  text-align: left;
+  cursor: pointer;
+}
+
+.protocol-name {
+  width: 100%;
+  height: 32px;
+  background: #fff;
+  border: 1px solid #ddd;
+  border-radius: 4px;
+}
+
+.flex-query {
+  margin: 16px 0;
+}
+
+.button-margin {
+  margin: 0 12px 0 16px;
+}
+
 .footer-margin {
   margin-top: 24px;
 }
@@ -670,7 +777,6 @@ onMounted(() => {
   margin-right: 5px;
   margin-bottom: 2px;
   color: #b2b2b2;
-  cursor: pointer;
 }
 
 .own-input {