Przeglądaj źródła

注册流程验证方式改为向邮箱发邮件

任一存 1 rok temu
rodzic
commit
b8cf492b19
3 zmienionych plików z 116 dodań i 80 usunięć
  1. 14 0
      game/src/api.js
  2. BIN
      game/src/assets/images/icon-mail.png
  3. 102 80
      game/src/views/SignUp.vue

+ 14 - 0
game/src/api.js

@@ -98,6 +98,20 @@ export async function checkLoginStatusAndProcess() {
     return false
   }
 }
+export async function sendEmail(address) {
+  const res = await axios({
+    method: 'post',
+    url: `${process.env.VUE_APP_DEPLOY_ORIGIN}/api/show/sendEmail`,
+    data: {
+      userName: address,
+    },
+  })
+  if (res.data.code !== 0) {
+    throw (`${res.data.msg}`)
+  } else {
+    return
+  }
+}
 export async function signUp(account, phone, password, verifiCode) {
   const pwdEncrypted = encodeStr(Base64.encode(password))
   const res = await axios({

BIN
game/src/assets/images/icon-mail.png


+ 102 - 80
game/src/views/SignUp.vue

@@ -31,6 +31,35 @@
         @blur="isAccountInputOver=true"
       >
     </div>
+    <div class="form-item form-item-verifi">
+      <div class="title">
+        <img
+          src="@/assets/images/icon-mail.png"
+          alt=""
+          draggable="false"
+        >
+        <span>邮箱验证码</span>
+      </div>
+      <div class="row">
+        <input
+          v-model="verifiCode"
+          placeholder="请输入4位验证码"
+          :class="{
+            invalid: isVerifiCodeInputOver && !isVerifiCodeValid
+          }"
+          @blur="isVerifiCodeInputOver=true"
+        >
+        <button
+          class="get-verifi-code"
+          :class="{
+            disabled: isVerifiCodeSent
+          }"
+          @click="onClickVerifiCode"
+        >
+          {{ isVerifiCodeSent ? `${verifiCodeCountDown}s` : '发送验证码' }}
+        </button>
+      </div>
+    </div>
     <div class="form-item">
       <div class="title">
         <img
@@ -88,44 +117,12 @@
         @blur="isPasswordRepeatInputOver=true"
       >
     </div>
-    <div class="form-item form-item-verifi">
-      <div class="title">
-        <!-- <img
-          src="@/assets/images/icon-lock.png"
-          alt=""
-          draggable="false"
-        > -->
-        <span>验证码</span>
-      </div>
-      <div class="row">
-        <input
-          v-model="verifiCode"
-          placeholder="请输入验证码"
-          :class="{
-            invalid: isVerifiCodeInputOver && !isVerifiCodeValid
-          }"
-          @blur="isVerifiCodeInputOver=true"
-        >
-        <button
-          class="get-verifi-code"
-          @click="onClickVerifiCode"
-        >
-          <img
-            v-if="isShowVerifiCode"
-            class=""
-            :src="`${$env.VUE_APP_DEPLOY_ORIGIN}/api/show/getRandCode`"
-            alt=""
-            draggable="false"
-          >
-        </button>
-      </div>
-    </div>
 
     <button
       class="submit"
       @click="submit"
     >
-      注册并登录
+      注册
     </button>
     <button
       class="return"
@@ -140,8 +137,8 @@
 import { ref, computed, watch, onMounted, nextTick, inject } from "vue"
 import { useRoute, useRouter } from "vue-router"
 import { useStore } from "vuex"
-import { showDialog } from 'vant'
-import { signUp, login } from '@/api.js'
+import { showDialog, showNotify } from 'vant'
+import { sendEmail, signUp, login } from '@/api.js'
 
 const route = useRoute()
 const router = useRouter()
@@ -155,14 +152,17 @@ const {
 } = useSizeAdapt(390, 752)
 
 const account = ref('')
+const verifiCode = ref('')
 const phone = ref('')
 const password = ref('')
 const passwordRepeat = ref('')
-const verifiCode = ref('')
 
 const accountTrimed = computed(() => {
   return account.value.trim()
 })
+const verifiCodeTrimed = computed(() => {
+  return verifiCode.value.trim()
+})
 const phoneTrimed = computed(() => {
   return phone.value.toString().trim()
 })
@@ -172,12 +172,14 @@ const passwordTrimed = computed(() => {
 const passwordRepeatTrimed = computed(() => {
   return passwordRepeat.value.trim()
 })
-const verifiCodeTrimed = computed(() => {
-  return verifiCode.value.trim()
-})
+
 
 const isAccountValid = computed(() => {
-  return !!accountTrimed.value
+  const pattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
+  return pattern.test(accountTrimed.value)
+})
+const isVerifiCodeValid = computed(() => {
+  return verifiCodeTrimed.value.length > 0
 })
 const isPhoneValid = computed(() => {
   return phoneTrimed.value.length === 11
@@ -188,33 +190,71 @@ const isPasswordValid = computed(() => {
 const isPasswordRepeatValid = computed(() => {
   return passwordTrimed.value === passwordRepeatTrimed.value
 })
-const isVerifiCodeValid = computed(() => {
-  return verifiCodeTrimed.value.length > 0
-})
+
 
 const isAccountInputOver = ref(false)
+const isVerifiCodeInputOver = ref(false)
 const isPhoneInputOver = ref(false)
 const isPasswordInputOver = ref(false)
 const isPasswordRepeatInputOver = ref(false)
-const isVerifiCodeInputOver = ref(false)
 
-const isShowVerifiCode = ref(true)
+// todo: 倒计时搬移到组件外部
+const isVerifiCodeSent = ref(false)
+const verifiCodeCountDown = ref(60)
+watch(isVerifiCodeSent, (v) => {
+  if (v) {
+    setInterval(() => {
+      verifiCodeCountDown.value--
+      if (verifiCodeCountDown.value === 0) {
+        isVerifiCodeSent.value = false
+        verifiCodeCountDown.value = 60
+      }
+    }, 1000)
+  }
+})
 const onClickVerifiCode = utils.throttle(() => {
-  isShowVerifiCode.value = false
-  nextTick(() => {
-    isShowVerifiCode.value = true
+  if (isVerifiCodeSent.value) {
+    return
+  }
+  if (!isAccountValid.value) {
+    showDialog({
+      message: '请正确输入邮箱',
+      theme: 'round-button',
+    })
+    isAccountInputOver.value = true
+    return
+  }
+  sendEmail(accountTrimed.value).then(() => {
+    showNotify({
+      type: 'success',
+      message: `验证码已发送至邮箱${accountTrimed.value},请在邮箱中查收`,
+    })
+    isVerifiCodeSent.value = true
+  }).catch((e) => {
+    showDialog({
+      message: e,
+      theme: 'round-button',
+    })
   })
 }, 333)
 
 function submit() {
   if (!isAccountValid.value) {
     showDialog({
-      message: '请正确输入邮箱',
+      message: '请输入正确的邮箱信息',
       theme: 'round-button',
     })
     isAccountInputOver.value = true
     return
   }
+  if (!isVerifiCodeValid.value) {
+    showDialog({
+      message: '正确输入验证码',
+      theme: 'round-button',
+    })
+    isVerifiCodeInputOver.value = true
+    return
+  }
   if (!isPhoneValid.value) {
     showDialog({
       message: '请正确输入手机号',
@@ -239,22 +279,12 @@ function submit() {
     isPasswordRepeatInputOver.value = true
     return
   }
-  if (!isVerifiCodeValid.value) {
-    showDialog({
-      message: '请输入验证码',
-      theme: 'round-button',
-    })
-    isVerifiCodeInputOver.value = true
-    return
-  }
 
   signUp(accountTrimed.value, phoneTrimed.value, passwordTrimed.value, verifiCodeTrimed.value).then(() => {
     showDialog({
       message: '注册成功',
       theme: 'round-button',
     }).then(() => {
-      login(accountTrimed.value, passwordTrimed.value)
-    }).then(() => {
       router.replace({
         name: 'HomeView'
       })
@@ -341,24 +371,6 @@ function submit() {
     }
   }
   >.form-item{
-    >.title{
-      width: 100%;
-      display: flex;
-      align-items: center;
-      margin-bottom: calc(16 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-      >img{
-        width: calc(22 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        height: calc(22 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        margin-right: calc(10 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-      }
-      >span{
-        font-size: calc(16 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        font-family: Source Han Sans SC, Source Han Sans SC;
-        font-weight: 400;
-        color: #D1B489;
-        line-height: calc(19 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-      }
-    }
     >div.row{
       display: flex;
       justify-content: space-between;
@@ -385,9 +397,19 @@ function submit() {
         border-bottom: 1px solid red;
       }
       >button.get-verifi-code{
-        height: calc(40 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        >img{
-          height: 100%;
+        width: calc(108 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        height: calc(34 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        background: #FFFFFF;
+        border-radius: calc(3 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        border: 1px solid #D1B489;
+        font-family: Source Han Sans SC, Source Han Sans SC;
+        font-weight: 400;
+        font-size: calc(16 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        color: #D1B489;
+        line-height: calc(19 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        text-align: center;
+        &.disabled{
+          pointer-events: none;
         }
       }
     }