Przeglądaj źródła

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

wangshun 2 miesięcy temu
rodzic
commit
d73b561512
1 zmienionych plików z 342 dodań i 174 usunięć
  1. 342 174
      src/views/register-gateway/BindProtocol.vue

+ 342 - 174
src/views/register-gateway/BindProtocol.vue

@@ -1,7 +1,9 @@
 <script setup lang="ts">
-import { onMounted, reactive, ref } from 'vue';
+import { onMounted, reactive, ref, useTemplateRef } from 'vue';
 import { message } from 'ant-design-vue';
 
+import ConfirmModal from '@/components/ConfirmModal.vue';
+import SvgIcon from '@/components/SvgIcon.vue';
 import { useRequest } from '@/hooks/request';
 import { t } from '@/i18n';
 import {
@@ -24,6 +26,7 @@ import type {
   InterfaceData,
   OptionItem,
   ProtocolItem,
+  ProtocolList,
   ProtocolsItem,
   RegisterGatewayForm,
   UseGuideStepItemProps,
@@ -35,7 +38,7 @@ const { handleRequest } = useRequest();
 const props = defineProps<UseGuideStepItemProps<RegisterGatewayForm>>();
 
 const interfaceData = ref<InterfaceData[]>([]);
-const value2 = ref('2');
+const agreementKey = ref<string>('own');
 
 const agreementForm = reactive<AgreementForm>({
   baudRate: 0,
@@ -56,6 +59,13 @@ const agreementData = ref<AgreementData[]>([]);
 const baudRatelist = ref<OptionItem<number>[]>([]);
 
 const protocolList = ref<ProtocolItem[]>([]);
+const protocolQuery = ref<ProtocolList>({
+  pageIndex: 1,
+  pageSize: 10,
+  searchContent: '',
+});
+
+const protocolTotal = ref<number>(0);
 
 const formRef = ref<FormInstance>();
 
@@ -64,7 +74,7 @@ const protocolsItem = reactive<AgreementData>({
   station: '',
   name: '',
   protocolName: '',
-  dev: '',
+  deviceName: '',
   dataSendInterval: 0,
   highFreqSendInterval: 0,
   protocolId: 0,
@@ -81,6 +91,8 @@ let advancedIndex: number;
 
 let verificationAgreement: VerificationAgreement[] = [];
 
+const modalComponentRef = useTemplateRef('modalComponent');
+
 let data: ProtocolsItem[] = [];
 
 const columns = [
@@ -88,32 +100,36 @@ const columns = [
     title: t('setupProtocol.protocolType'),
     dataIndex: 'protocolType',
     key: 'protocolType',
-    width: 170,
+    ellipsis: true,
   },
   {
     title: t('registerGateway.stationNumber'),
     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: 220,
+    width: 240,
   },
   {
     title: t('registerGateway.associatedEquipment'),
-    key: 'dev',
-    dataIndex: 'dev',
+    key: 'deviceName',
+    dataIndex: 'deviceName',
+    ellipsis: true,
   },
   {
     title: t('common.operation'),
     key: 'action',
+    width: 90,
   },
 ];
 
@@ -135,28 +151,23 @@ const protocolColumns = [
   },
 ];
 
-const options2 = ref([
-  {
-    value: '1',
-    payload: t('registerGateway.platformAgreement'),
-  },
-  {
-    value: '2',
-    payload: t('registerGateway.proprietaryProtocol'),
-  },
-]);
-
 const postGetList = () => {
   handleRequest(async () => {
     interfaceData.value = await gatewayLinkGetList(props.form.id);
   });
 };
 
-const addDelete = (value: number) => {
+const confirm = () => {
   handleRequest(async () => {
-    await gatewayLinkDelete(value);
+    await gatewayLinkDelete(agreementId);
     postGetList();
   });
+  modalComponentRef.value?.hideView();
+};
+
+const addDelete = (value: number) => {
+  agreementId = value;
+  modalComponentRef.value?.showView();
 };
 
 const addSlave = () => {
@@ -165,10 +176,10 @@ const addSlave = () => {
     station: '',
     name: '',
     protocolName: '',
-    dev: '',
+    deviceName: '',
     dataSendInterval: 0,
     highFreqSendInterval: 0,
-    protocolId: 0,
+    protocolId: undefined,
     isStandard: '0',
   });
 };
@@ -178,49 +189,49 @@ const bindingAgreement = () => {
   formRef.value
     ?.validate()
     .then(() => {
+      if (!agreementData.value.length) {
+        return message.warning(t('registerGateway.prompt'));
+      }
+
       handleRequest(async () => {
-        if (agreementData.value.length) {
-          agreementData.value.forEach((item) => {
-            const { protocolId, station, isStandard, dataSendInterval, highFreqSendInterval } = item;
-            data.push({
-              protocolId,
-              station,
-              isStandard,
-              dataSendInterval,
-              highFreqSendInterval,
-            });
+        agreementData.value.forEach((item) => {
+          const { protocolId, station, isStandard, dataSendInterval, highFreqSendInterval } = item;
+          data.push({
+            protocolId,
+            station,
+            isStandard,
+            dataSendInterval,
+            highFreqSendInterval,
           });
+        });
 
-          await gatewayLinkProtocolReset({
-            linkId: agreementId,
-            protocols: data,
-          });
+        await gatewayLinkProtocolReset({
+          linkId: agreementId,
+          protocols: data,
+        });
 
-          const { linkName, interfaceId, gatewayId, bindState } = interfaceData.value[interfaceIndex];
-          const { dataBit, parityBit, stopBit, baudRate, readTimeout, nextDataReadDelay, nextRoundDataReadDelay } =
-            agreementForm;
-
-          await gatewayLinkUpdate({
-            id: agreementId,
-            linkName,
-            interfaceId,
-            gatewayId,
-            bindState,
-            dataBit,
-            parityBit,
-            stopBit,
-            baudRate,
-            readTimeout,
-            nextDataReadDelay,
-            nextRoundDataReadDelay,
-          });
+        const { linkName, interfaceId, gatewayId, bindState } = interfaceData.value[interfaceIndex];
+        const { dataBit, parityBit, stopBit, baudRate, readTimeout, nextDataReadDelay, nextRoundDataReadDelay } =
+          agreementForm;
+
+        await gatewayLinkUpdate({
+          id: agreementId,
+          linkName,
+          interfaceId,
+          gatewayId,
+          bindState,
+          dataBit,
+          parityBit,
+          stopBit,
+          baudRate,
+          readTimeout,
+          nextDataReadDelay,
+          nextRoundDataReadDelay,
+        });
 
-          open.value = false;
+        open.value = false;
 
-          postGetList();
-        } else {
-          message.warning(t('registerGateway.prompt'));
-        }
+        postGetList();
       });
     })
     .catch(() => {});
@@ -243,17 +254,19 @@ const replaceAgreement = (value: number) => {
   open1.value = true;
 
   handleRequest(async () => {
-    const { records } = await postProtocolCandidatesList(
-      {
-        pageIndex: 1,
-        pageSize: 10,
-      },
-      props.form.id,
-    );
+    const { records, total } = await postProtocolCandidatesList(protocolQuery.value, props.form.id);
+    protocolTotal.value = total;
     protocolList.value = records;
   });
 };
 
+const agreementQuery = () => {
+  replaceAgreement(agreementIndex);
+};
+const switchPages = () => {
+  replaceAgreement(agreementIndex);
+};
+
 const rules1: Record<string, Rule[]> = {
   dataSendInterval: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
   highFreqSendInterval: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
@@ -278,11 +291,6 @@ const interfaceShow = (value: string) => {
   return value === 'LAN' ? 'background-color: rgba(54, 207, 201, 1);' : 'background-color: rgba(89, 126, 247, 1);';
 };
 
-// 根据条件显示编辑/绑定文本
-const textShow = (value: number) => {
-  return value === 0 ? t('common.binding') : t('common.revise');
-};
-
 // 显示绑定/编辑弹框
 const addEditor = (value: number, index: number, bindState: number) => {
   agreementId = value;
@@ -307,11 +315,18 @@ const addEditor = (value: number, index: number, bindState: number) => {
       verificationAgreement = await gatewayLinkList(agreementId);
 
       verificationAgreement.forEach((item) => {
-        const { protocolType, station, protocolName, dataSendInterval, highFreqSendInterval, protocolId, isStandard } =
-          item;
+        const {
+          protocolType,
+          station,
+          protocolName,
+          dataSendInterval,
+          highFreqSendInterval,
+          protocolId,
+          isStandard,
+          deviceName,
+        } = item;
         agreementData.value.push({
           name: '',
-          dev: '',
           protocolType,
           station: String(station),
           protocolName,
@@ -319,6 +334,7 @@ const addEditor = (value: number, index: number, bindState: number) => {
           highFreqSendInterval,
           protocolId,
           isStandard: String(isStandard),
+          deviceName,
         });
       });
     }
@@ -332,19 +348,23 @@ const handleOk = () => {
 };
 
 const handleOk1 = () => {
-  const { protocolName, baudRate, dataSendInterval, highFreqSendInterval, id } = protocolItem;
-  agreementData.value[agreementIndex] = {
-    protocolType: String(baudRate),
-    station: '',
-    name: '',
-    protocolName,
-    dev: '',
-    dataSendInterval,
-    highFreqSendInterval,
-    protocolId: id,
-    isStandard: '0',
-  };
-  open1.value = false;
+  if (protocolItem) {
+    const { protocolName, dataSendInterval, highFreqSendInterval, id, protocolType } = protocolItem;
+    agreementData.value[agreementIndex] = {
+      protocolType,
+      station: '',
+      name: '',
+      protocolName,
+      deviceName: '',
+      dataSendInterval,
+      highFreqSendInterval,
+      protocolId: id,
+      isStandard: '0',
+    };
+    open1.value = false;
+  } else {
+    return message.warning(t('registerGateway.pleaseSelectAgreement'));
+  }
 };
 
 onMounted(() => {
@@ -353,18 +373,17 @@ onMounted(() => {
 </script>
 
 <template>
-  <div>
-    <div class="use-guide-title">{{ $t('registerGateway.bindingAgreement') }}</div>
-    <div class="use-guide-description">文本描述!!!</div>
-    <div class="interface-content">
-      <ABadge v-for="(item, index) in interfaceData" :key="item.id">
-        <template #count v-if="item.bindState === 1">
-          <img referrerpolicy="no-referrer" src="@/assets/img/checked.png" />
-        </template>
-        <AFlex class="interface-div" justify="flex-start" align="center">
-          <ARow style="width: 100%">
-            <ACol :span="14">
-              <AFlex justify="flex-start" align="center">
+  <div class="renegotiation-agreement">
+    <div class="use-guide-title">{{ $t('registerGateway.interfaceList') }}</div>
+    <AFlex wrap="wrap">
+      <AFlex v-for="(item, index) in interfaceData" :key="item.id" class="interface-list" align="center">
+        <AFlex align="center">
+          <ABadge>
+            <template #count v-if="item.bindState === 1">
+              <SvgIcon class="agreement-circle" name="check-circle" />
+            </template>
+            <AFlex class="interface-div" justify="space-between" align="center">
+              <AFlex align="center">
                 <AFlex
                   class="interface-div1"
                   :style="interfaceShow(item.interfaceType)"
@@ -373,32 +392,34 @@ onMounted(() => {
                 >
                   <span class="interface-div1-span">{{ item.interfaceType }}</span>
                 </AFlex>
-
                 <div class="interface-div2">{{ item.linkName }}</div>
               </AFlex>
-            </ACol>
-            <ACol :span="10">
-              <AFlex justify="flex-end" align="center">
-                <AButton
-                  style="margin-top: 10px; color: #1890ff"
-                  type="link"
-                  danger
-                  @click="addEditor(item.id, index, item.bindState)"
-                  >{{ textShow(item.bindState) }}</AButton
-                >
-                <AButton style="margin-top: 8px; margin-right: 10px" type="link" danger @click="addDelete(item.id)">{{
-                  $t('common.delete')
-                }}</AButton>
+
+              <AFlex align="center">
+                <div class="interface-agreement">{{ item.protocolType }}</div>
               </AFlex>
-            </ACol>
-          </ARow>
+            </AFlex>
+          </ABadge>
+
+          <div @click="addEditor(item.id, index, item.bindState)">
+            <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" />
+            </AFlex>
+          </div>
+
+          <div @click="addDelete(item.id)">
+            <AFlex class="interface-but" justify="center" align="center">
+              <SvgIcon class="interface-but-icon" name="delete" />
+            </AFlex>
+          </div>
         </AFlex>
-      </ABadge>
-    </div>
+      </AFlex>
+    </AFlex>
     <AModal
       v-model:open="open"
-      :closable="false"
-      width="1100px"
+      :title="$t('registerGateway.bindingAgreement')"
+      width="920px"
       :footer="null"
       :mask-closable="false"
       :keyboard="false"
@@ -412,7 +433,7 @@ onMounted(() => {
         :rules="rules"
         :wrapper-col="{ span: 21 }"
       >
-        <ARow style="margin-top: 40px">
+        <ARow>
           <ACol :span="6">
             <AFormItem :label="$t('setupProtocol.baudRate')" name="baudRate">
               <ASelect
@@ -479,13 +500,13 @@ onMounted(() => {
           </ACol>
         </ARow>
       </AForm>
-      <ATable :columns="columns" :data-source="agreementData" :pagination="false" :scroll="{ y: 350 }">
+      <ATable :columns="columns" :data-source="agreementData" :pagination="false">
         <template #bodyCell="{ column, record, index }">
           <template v-if="column.key === 'protocolType'">
             <AInput disabled v-model:value="record.protocolType" />
           </template>
           <template v-else-if="column.key === 'station'">
-            <AInput v-model:value="record.station" />
+            <AInputNumber v-model:value="record.station" :min="1" />
           </template>
           <template v-else-if="column.key === 'name'">
             <AInput disabled v-model:value="record.name" />
@@ -493,26 +514,38 @@ onMounted(() => {
           <template v-else-if="column.key === 'protocolName'">
             <AInputSearch disabled v-model:value="record.protocolName">
               <template #enterButton>
-                <AButton style="color: #32bac0" @click="replaceAgreement(index)">{{
+                <AButton class="button-color" @click="replaceAgreement(index)">{{
                   $t('registerGateway.renegotiationAgreement')
                 }}</AButton>
               </template>
             </AInputSearch>
           </template>
+          <template v-else-if="column.key === 'deviceName'">
+            <AFlex justify="center" align="center" class="device-name-tag">
+              {{ record.deviceName }}
+            </AFlex>
+          </template>
+
           <template v-else-if="column.key === 'action'">
-            <AButton @click="advancedSettings(record as AgreementData, index)">{{ $t('common.settings') }}</AButton>
-            <AButton @click="deleteAgreement(index)">{{ $t('common.delete') }}</AButton>
+            <SvgIcon
+              class="agreement-icon agreement-icon-right"
+              name="setting"
+              @click="advancedSettings(record as AgreementData, index)"
+            />
+            <SvgIcon class="agreement-icon" name="delete" @click="deleteAgreement(index)" />
           </template>
         </template>
       </ATable>
 
       <AFlex justify="space-between">
-        <div class="but-text" @click="addSlave">
-          <span>{{ $t('registerGateway.addStation') }}</span>
-        </div>
-        <div style="margin-top: 24px">
+        <AButton class="icon-button but-text" type="text" @click="addSlave">
+          <SvgIcon name="plus" />
+          {{ $t('registerGateway.addStation') }}
+        </AButton>
+
+        <div class="footer-margin">
           <AButton class="off-but" @click="open = false">{{ $t('common.turnOff') }}</AButton>
-          <AButton type="primary" @click="bindingAgreement">{{ $t('common.save') }}</AButton>
+          <AButton class="off-but-width" type="primary" @click="bindingAgreement">{{ $t('common.save') }}</AButton>
         </div>
       </AFlex>
     </AModal>
@@ -522,36 +555,60 @@ onMounted(() => {
       :title="$t('registerGateway.renegotiationAgreement')"
       :ok-text="$t('common.confirm')"
       :cancel-text="$t('common.cancel')"
-      width="1100px"
+      width="920px"
       @ok="handleOk1"
       :mask-closable="false"
       :keyboard="false"
     >
-      <ARow style="margin-top: 40px; margin-bottom: 10px">
-        <ACol :span="12">
-          <ASegmented class="agreement-segmented" v-model:value="value2" :options="options2">
-            <template #label="{ payload }">
-              <div style="padding: 4px">
-                <div>{{ payload }}</div>
-              </div>
-            </template>
-          </ASegmented>
-        </ACol>
-        <ACol :span="12">
+      <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 style="width: 50%" :placeholder="$t('registerGateway.pleaseProtocolName')" />
+            <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>
-        </ACol>
-      </ARow>
-      <ATable
-        :row-selection="{
-          type: 'radio',
-          onChange: rowSelectedChange,
-        }"
-        row-key="id"
-        :columns="protocolColumns"
-        :data-source="protocolList"
-      />
+        </template>
+      </ATabs>
     </AModal>
 
     <AModal
@@ -559,38 +616,144 @@ onMounted(() => {
       :title="$t('registerGateway.advancedSettingsAgreement')"
       :ok-text="$t('common.confirm')"
       :cancel-text="$t('common.cancel')"
-      width="500px"
+      width="480px"
       @ok="handleOk"
       :mask-closable="false"
       :keyboard="false"
     >
-      <AForm :model="protocolsItem" label-align="left" layout="vertical" :rules="rules1" :wrapper-col="{ span: 20 }">
-        <ARow style="margin-top: 40px">
-          <ACol :span="12">
-            <AFormItem :label="$t('registerGateway.dataReportingFrequency')" name="dataSendInterval">
-              <AInput v-model:value="protocolsItem.dataSendInterval" placeholder="Basic usage" /> </AFormItem
-          ></ACol>
-          <ACol :span="12"
-            ><AFormItem :label="$t('registerGateway.highDataFrequencyReportingFrequency')" name="highFreqSendInterval">
-              <AInput v-model:value="protocolsItem.highFreqSendInterval" placeholder="Basic usage" /> </AFormItem
-          ></ACol>
-        </ARow>
+      <AForm :model="protocolsItem" layout="vertical" :rules="rules1">
+        <AFormItem :label="$t('registerGateway.dataReportingFrequency')" name="dataSendInterval">
+          <AInput v-model:value="protocolsItem.dataSendInterval" placeholder="Basic usage" />
+        </AFormItem>
+        <AFormItem :label="$t('registerGateway.highDataFrequencyReportingFrequency')" name="highFreqSendInterval">
+          <AInput v-model:value="protocolsItem.highFreqSendInterval" placeholder="Basic usage" />
+        </AFormItem>
       </AForm>
     </AModal>
+
+    <ConfirmModal
+      ref="modalComponent"
+      :title="$t('common.deleteConfirmation')"
+      :description-text="$t('registerGateway.deleteInterface')"
+      :icon="{ name: 'delete' }"
+      :icon-bg-color="'#F56C6C'"
+      @confirm="confirm"
+    />
   </div>
 </template>
 
 <style lang="scss" scoped>
+.footer-margin {
+  margin-top: 24px;
+}
+
+.button-color {
+  color: var(--antd-color-primary-hover) !important;
+}
+
+.device-name-tag {
+  width: 100%;
+  height: 32px;
+  color: #000;
+  background: #e1f5f6;
+  border-radius: 4px;
+}
+
+.agreement-circle {
+  font-size: 24px;
+  color: var(--antd-color-primary-hover);
+}
+
+.search-svg {
+  width: 12px;
+  height: 12px;
+  margin-right: 5px;
+  margin-bottom: 2px;
+  color: #b2b2b2;
+  cursor: pointer;
+}
+
+.own-input {
+  width: 256px;
+  border: 1px solid #d6d6d6;
+  border-radius: 4px;
+}
+
+.footer-pagination {
+  margin-top: 24px;
+}
+
+:deep(.renegotiation-agreement) {
+  .ant-tabs-nav::before {
+    border: 0;
+  }
+}
+
+.agreement-icon-right {
+  margin-right: 15px;
+}
+
+.agreement-icon {
+  font-size: 21px;
+  color: var(--antd-color-primary-hover);
+  cursor: pointer;
+}
+
+.use-guide-title {
+  margin-top: 40px;
+  margin-bottom: 16px;
+  font-size: 16px;
+  font-style: normal;
+  font-weight: 500;
+  line-height: 24px;
+  color: rgb(0 0 0 / 85%);
+  text-align: left;
+}
+
+.interface-but {
+  width: 32px;
+  height: 32px;
+  margin-left: 16px;
+  cursor: pointer;
+  background: #fff;
+  border: 1px solid #d9d9d9;
+  border-radius: 4px;
+}
+
+.interface-but-icon {
+  font-size: 14px;
+  color: #f56e6e;
+}
+
+.interface-but-color {
+  font-size: 14px;
+}
+
+.interface-agreement {
+  margin-top: 6px;
+  margin-right: 24px;
+  font-size: 14px;
+  font-style: normal;
+  font-weight: 400;
+  line-height: 22px;
+  color: #666;
+  text-align: right;
+}
+
+.interface-list {
+  margin-right: 80px;
+  margin-bottom: 16px;
+}
+
 .interface-content {
   width: 570px;
   margin-top: 24px;
 }
 
 .interface-div {
-  width: 457px;
-  height: 67px;
-  margin-bottom: 14px;
-  background-color: rgb(240 240 240 / 100%);
+  width: 458px;
+  height: 72px;
+  background: #f5f7fa;
   border-radius: 8px;
 }
 
@@ -620,7 +783,7 @@ onMounted(() => {
 }
 
 .protocol-class .ant-form-item {
-  margin-bottom: 15px !important;
+  margin-bottom: 24px !important;
 }
 
 .dev-list {
@@ -649,14 +812,19 @@ onMounted(() => {
   font-style: normal;
   font-weight: 400;
   line-height: 24px;
-  color: #32bac0;
+  color: var(--antd-color-primary-hover);
   text-align: left;
   cursor: pointer;
 }
 
 .off-but {
+  width: 76px;
   margin-right: 16px;
-  color: #32bac0;
-  border-color: #32bac0;
+  color: var(--antd-color-primary-hover);
+  border-color: var(--antd-color-primary-hover);
+}
+
+.off-but-width {
+  width: 76px;
 }
 </style>