Jelajahi Sumber

perf(components): 优化 UseGuidance 组件,支持表单配置

wangcong 3 bulan lalu
induk
melakukan
524d81b45a

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

@@ -35,6 +35,7 @@
     "howToJudgeProtocolType": "如何判断协议类型",
     "importFromTemplate": "从模板导入",
     "manuallyCreate": "手动创建",
+    "plzSelectProtocolType": "请选择协议类型",
     "protocolType": "协议类型",
     "recognizeProgress": "识别中",
     "recognizeTip": "预计 {time} 秒后完成识别",

+ 17 - 4
src/layout/UseGuidance.vue

@@ -1,4 +1,4 @@
-<script setup lang="ts">
+<script setup lang="ts" generic="T extends Record<string, any>">
 import { computed, ref } from 'vue';
 import { useRouter } from 'vue-router';
 
@@ -6,11 +6,14 @@ import { t } from '@/i18n';
 import { addUnit } from '@/utils';
 
 import type { Component, CSSProperties } from 'vue';
-import type { UseGuideStepItem } from '@/types';
+import type { FormInstance } from 'ant-design-vue';
+import type { FormRules, UseGuideStepItem } from '@/types';
 
 interface Props {
   title: string;
   steps: UseGuideStepItem[];
+  form: T;
+  rules: FormRules<T>;
   contentOffset?: number;
 }
 
@@ -18,6 +21,7 @@ const props = defineProps<Props>();
 
 const router = useRouter();
 const current = ref(0);
+const formRef = ref<FormInstance>();
 
 const isFirstStep = computed(() => {
   return current.value === 0;
@@ -61,7 +65,14 @@ const finishCurrentStep = () => {
     return;
   }
 
-  goNextStep();
+  formRef.value
+    ?.validate()
+    .then(() => {
+      goNextStep();
+    })
+    .catch((err) => {
+      console.error(err);
+    });
 };
 </script>
 
@@ -79,7 +90,9 @@ const finishCurrentStep = () => {
     </ALayoutSider>
     <ALayout>
       <ALayoutContent class="use-guide-main" :style="contentStyle">
-        <Component :is="currentComponent" />
+        <AForm ref="formRef" :model="form" :rules="rules">
+          <Component :is="currentComponent" :form="form" />
+        </AForm>
       </ALayoutContent>
       <ALayoutFooter class="use-guide-footer">
         <AButton type="text" :disabled="isLastStep" @click="goNextStep">{{ $t('common.skip') }}</AButton>

+ 17 - 0
src/types/index.ts

@@ -1,8 +1,25 @@
 import type { Component } from 'vue';
 import type { StepProps } from 'ant-design-vue';
+import type { Rule } from 'ant-design-vue/es/form';
+import type { ProtocolConfigMethod } from '@/constants';
+
+export type FormRules<T> = {
+  [K in keyof T]?: Rule[];
+} & {
+  [key: string]: Rule[];
+};
 
 export interface UseGuideStepItem extends StepProps {
   title: string;
   component: Component;
   contentOffset?: number;
 }
+
+export interface UseGuideStepItemProps<T> {
+  form: T;
+}
+
+export interface SetupProtocolForm {
+  protocolType: string;
+  configMethod: ProtocolConfigMethod;
+}

+ 5 - 1
src/views/setup-protocol/SelectConfigMethod.vue

@@ -1,12 +1,16 @@
 <script setup lang="ts">
 import { ProtocolConfigMethod } from '@/constants';
+
+import type { SetupProtocolForm, UseGuideStepItemProps } from '@/types';
+
+defineProps<UseGuideStepItemProps<SetupProtocolForm>>();
 </script>
 
 <template>
   <div>
     <div class="use-guide-title">{{ $t('setupProtocol.selectConfigMethod') }}</div>
     <div class="use-guide-description config-description">{{ $t('setupProtocol.selectConfigMethodTip') }}</div>
-    <ARadioGroup>
+    <ARadioGroup v-model:value="form.configMethod">
       <ARadio :value="ProtocolConfigMethod.ImportFromTemplate">{{ $t('setupProtocol.importFromTemplate') }}</ARadio>
       <ARadio :value="ProtocolConfigMethod.ManuallyCreate">{{ $t('setupProtocol.manuallyCreate') }}</ARadio>
     </ARadioGroup>

+ 5 - 1
src/views/setup-protocol/SelectProtocolType.vue

@@ -1,5 +1,9 @@
 <script setup lang="ts">
 import { ProtocolType } from '@/constants';
+
+import type { SetupProtocolForm, UseGuideStepItemProps } from '@/types';
+
+defineProps<UseGuideStepItemProps<SetupProtocolForm>>();
 </script>
 
 <template>
@@ -7,7 +11,7 @@ import { ProtocolType } from '@/constants';
     <div class="use-guide-title">{{ $t('setupProtocol.selectProtocolType') }}</div>
     <div class="use-guide-description">{{ $t('setupProtocol.selectProtocolTypeTip') }}</div>
     <AFormItem :label="$t('setupProtocol.protocolType')" name="protocolType">
-      <ASelect class="protocol-select" :placeholder="$t('common.plzSelect')">
+      <ASelect v-model:value="form.protocolType" class="protocol-select" :placeholder="$t('common.plzSelect')">
         <ASelectOption :value="ProtocolType.ModbusRTU">modbusRTU</ASelectOption>
         <ASelectOption :value="ProtocolType.S7">S7</ASelectOption>
       </ASelect>

+ 22 - 2
src/views/setup-protocol/SetupProtocol.vue

@@ -1,13 +1,16 @@
 <script setup lang="ts">
+import { computed, reactive } from 'vue';
+
 import UseGuidance from '@/layout/UseGuidance.vue';
 import { t } from '@/i18n';
+import { ProtocolConfigMethod } from '@/constants';
 
 import SelectConfigMethod from './SelectConfigMethod.vue';
 import SelectProtocolType from './SelectProtocolType.vue';
 import UploadProtocolFile from './UploadProtocolFile.vue';
 import WaitingRecognition from './WaitingRecognition.vue';
 
-import type { UseGuideStepItem } from '@/types';
+import type { FormRules, SetupProtocolForm, UseGuideStepItem } from '@/types';
 
 const steps: UseGuideStepItem[] = [
   {
@@ -27,8 +30,25 @@ const steps: UseGuideStepItem[] = [
     component: WaitingRecognition,
   },
 ];
+
+const setupProtocolForm = reactive<SetupProtocolForm>({
+  protocolType: '',
+  configMethod: ProtocolConfigMethod.ImportFromTemplate,
+});
+
+const rules = computed<FormRules<SetupProtocolForm>>(() => {
+  return {
+    protocolType: [
+      {
+        required: true,
+        message: t('setupProtocol.plzSelectProtocolType'),
+        trigger: 'change',
+      },
+    ],
+  };
+});
 </script>
 
 <template>
-  <UseGuidance :title="$t('setupProtocol.setupProtocol')" :steps="steps" />
+  <UseGuidance :title="$t('setupProtocol.setupProtocol')" :steps="steps" :form="setupProtocolForm" :rules="rules" />
 </template>