Преглед изворни кода

修改密码功能添加邮箱验证码步骤

任一存 пре 1 година
родитељ
комит
e68a81ace6
3 измењених фајлова са 118 додато и 6 уклоњено
  1. 2 1
      game/src/api.js
  2. 115 3
      game/src/views/ChangePassword.vue
  3. 1 2
      game/src/views/SignUp.vue

+ 2 - 1
game/src/api.js

@@ -147,7 +147,7 @@ export async function findPassowrd(account, phone, verifiCode) {
     return
   }
 }
-export async function changePassword(newPassword, oldPassword) {
+export async function changePassword(newPassword, oldPassword, verifiCode) {
   const pwdNewEncrypted = encodeStr(Base64.encode(newPassword))
   const pwdOldEncrypted = encodeStr(Base64.encode(oldPassword))
   const res = await axios({
@@ -156,6 +156,7 @@ export async function changePassword(newPassword, oldPassword) {
     data: {
       newPassword: pwdNewEncrypted,
       oldPassword: pwdOldEncrypted,
+      randCode: verifiCode,
     },
     headers: {
       token: store.state.token,

+ 115 - 3
game/src/views/ChangePassword.vue

@@ -68,6 +68,35 @@
         @blur="isPasswordRepeatInputOver=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>
 
     <button
       class="submit"
@@ -88,8 +117,8 @@
 import { ref, computed, watch, onMounted } from "vue"
 import { useRoute, useRouter } from "vue-router"
 import { useStore } from "vuex"
-import { showDialog } from 'vant'
-import { changePassword } from '@/api.js'
+import { showDialog, showNotify } from 'vant'
+import { sendEmail, changePassword } from '@/api.js'
 
 const route = useRoute()
 const router = useRouter()
@@ -103,6 +132,7 @@ const {
 const passwordOld = ref('')
 const password = ref('')
 const passwordRepeat = ref('')
+const verifiCode = ref('')
 
 const passwordOldTrimed = computed(() => {
   return passwordOld.value.trim()
@@ -113,6 +143,9 @@ const passwordTrimed = computed(() => {
 const passwordRepeatTrimed = computed(() => {
   return passwordRepeat.value.trim()
 })
+const verifiCodeTrimed = computed(() => {
+  return verifiCode.value.trim()
+})
 
 const isPasswordOldValid = computed(() => {
   return passwordOldTrimed.value.length >= 6 && passwordOldTrimed.value.length <= 10 && passwordTrimed.value.search(/^[0-9a-zA-Z].*$/) === 0
@@ -123,10 +156,45 @@ const isPasswordValid = computed(() => {
 const isPasswordRepeatValid = computed(() => {
   return passwordTrimed.value === passwordRepeatTrimed.value
 })
+const isVerifiCodeValid = computed(() => {
+  return verifiCodeTrimed.value.length > 0
+})
 
 const isPasswordOldInputOver = ref(false)
 const isPasswordInputOver = ref(false)
 const isPasswordRepeatInputOver = ref(false)
+const isVerifiCodeInputOver = ref(false)
+
+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(() => {
+  if (isVerifiCodeSent.value) {
+    return
+  }
+  sendEmail(store.state.userInfo.userName).then(() => {
+    showNotify({
+      type: 'success',
+      message: `验证码已发送至邮箱${store.state.userInfo.userName},请在邮箱中查收`,
+    })
+    isVerifiCodeSent.value = true
+  }).catch((e) => {
+    showDialog({
+      message: e,
+      theme: 'round-button',
+    })
+  })
+}, 333)
 
 function submit() {
   if (!isPasswordOldValid.value) {
@@ -154,7 +222,7 @@ function submit() {
     return
   }
 
-  changePassword(passwordTrimed.value, passwordOldTrimed.value).then(() => {
+  changePassword(passwordTrimed.value, passwordOldTrimed.value, verifiCode.value).then(() => {
     showDialog({
       message: '密码修改成功',
       theme: 'round-button',
@@ -239,6 +307,50 @@ function submit() {
       border-bottom: 1px solid red;
     }
   }
+  >.form-item{
+    >div.row{
+      display: flex;
+      justify-content: space-between;
+      align-items: flex-end;
+      margin-top: calc(-11 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      >input{
+        width: 50%;
+        height: calc(29 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        border-bottom: 1px solid #D9D9D9;
+        font-size: calc(16 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        font-family: Source Han Sans SC, Source Han Sans SC;
+        font-weight: 400;
+        color: black;
+        line-height: calc(19 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        &::placeholder {
+          font-size: calc(16 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          font-family: Source Han Sans SC, Source Han Sans SC;
+          font-weight: 400;
+          color: #B8B8B8;
+          line-height: calc(19 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        }
+      }
+      >input.invalid{
+        border-bottom: 1px solid red;
+      }
+      >button.get-verifi-code{
+        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;
+        }
+      }
+    }
+  }
   >button.submit{
     width: calc(332 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
     height: calc(56 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));

+ 1 - 2
game/src/views/SignUp.vue

@@ -138,7 +138,7 @@ import { ref, computed, watch, onMounted, nextTick, inject } from "vue"
 import { useRoute, useRouter } from "vue-router"
 import { useStore } from "vuex"
 import { showDialog, showNotify } from 'vant'
-import { sendEmail, signUp, login } from '@/api.js'
+import { sendEmail, signUp } from '@/api.js'
 
 const route = useRoute()
 const router = useRouter()
@@ -198,7 +198,6 @@ const isPhoneInputOver = ref(false)
 const isPasswordInputOver = ref(false)
 const isPasswordRepeatInputOver = ref(false)
 
-// todo: 倒计时搬移到组件外部
 const isVerifiCodeSent = ref(false)
 const verifiCodeCountDown = ref(60)
 watch(isVerifiCodeSent, (v) => {