Переглянути джерело

人机校验,同意勾选

lifanagju_citu 6 місяців тому
батько
коміт
057ffb4bd7

+ 35 - 18
src/components/VerificationCode/index.vue

@@ -1,6 +1,7 @@
 <template>
   <div>
     <v-form @submit.prevent ref="phoneForm">
+      <!-- 邀请新同事快捷登录时需要填写邮箱 -->
       <v-text-field
         v-if="props.showEmailInput"
         v-model="loginData.email"
@@ -47,30 +48,35 @@
       </v-text-field>
     </v-form>
   </div>
+  <Verify
+    v-if="props.openVerify"
+    ref="smsVerify"
+    captchaType="blockPuzzle"
+    :imgSize="{ width: '400px', height: '200px' }"
+    mode="pop"
+    @success="verifySuccess"
+  />
 </template>
 
 <script setup>
 defineOptions({ name: 'verification-code' })
-import { ref, reactive, nextTick } from 'vue'
+import { ref, reactive } from 'vue'
 import { setCodeTime } from '@/utils/code'
 import { checkEmail } from '@/utils/validate'
 import { sendSmsCode } from '@/api/common/index'
 import { useI18n } from '@/hooks/web/useI18n'
 import Snackbar from '@/plugins/snackbar'
+import Verify from '@/components/Verifition'
 
-const emits = defineEmits(['handleEnter', 'getCaptchaStr'])
+const emits = defineEmits(['handleEnter'])
 const { t } = useI18n()
 const props = defineProps({
   phoneDisabled: Boolean,
   phone: String,
-  openCaptcha: { // 是否开启人机验证
+  openVerify: { // 是否开启人机验证
     type: Boolean,
     default: false
   },
-  captchaStr: { // 人机验证码
-    type: String,
-    default: ''
-  },
   showEmailInput: { // 需要输入邮箱
     type: Boolean,
     default: false
@@ -122,6 +128,19 @@ const emailRules = ref([
 //   currentArea.value = e.value
 // }
 
+// 获取验证码
+const smsVerify = ref()
+const getCode = async () => {
+  // 弹出验证码 // 已开启:则展示验证码;只有完成验证码的情况,才进行登录
+  smsVerify.value.show()
+}
+// const captchaVerification = ref('')
+const verifySuccess = (params) => {
+  // captchaVerification.value = params.captchaVerification
+  loginData.captchaVerification = params.captchaVerification
+  handleCode()
+}
+
 // 获取验证码
 const showCode = ref(true)
 const count = ref(0)
@@ -131,15 +150,13 @@ const handleCode = () => {
     Snackbar.warning(t('login.mobileNumberPlaceholder'))
     return
   }
-  nextTick(() => {
-    if (props.openCaptcha && !props.captchaStr) {
-      emits('getCaptchaStr') // 在获取验证码之前加人机验证
-      return
-    }
-    count.value = 60
-    setTime()
-    getSmsCode()
-  })
+  if (props.openVerify && !loginData.captchaVerification) {
+    getCode()
+    return
+  }
+  count.value = 60
+  setTime()
+  getSmsCode()
 }
 
 const getSmsCode = async () => {
@@ -178,7 +195,8 @@ const loginUserPhone = localStorage.getItem('loginUserPhone') || ''
 const loginData = reactive({
   email: '',
   phone: loginUserPhone,
-  code: ''
+  code: '',
+  captchaVerification: ''
 })
 if (props.phone) loginData.phone = props.phone
 
@@ -196,7 +214,6 @@ const resetForm = () => {
 
 defineExpose({
   resetForm, 
-  handleCode, 
   loginData, 
   phoneForm
 })

+ 8 - 4
src/views/login/components/editPassword.vue

@@ -1,6 +1,6 @@
 <template>
-  <div>
-    <PhonePage ref="phoneRef" style="width: 370px;" :phone="phone" :scene="scene" :phoneDisabled="phone ? true : false"></PhonePage>
+  <div class="mt-3">
+    <PhonePage ref="phoneRef" style="width: 370px;" :phone="phone" :scene="scene" openVerify :phoneDisabled="phone ? true : false"></PhonePage>
     <v-form ref="passwordRef" style="width: 370px;">
       <v-text-field
         v-model="query.password"
@@ -29,10 +29,12 @@
     </v-form>
     <slot name="custom"></slot>
     <div class="text-center mt-5">
-      <v-btn v-if="showCancelBtn" class="mr-5" color="primary" variant="outlined" @click="handleClose">取 消</v-btn>
-      <v-btn color="primary" :max-width="showCancelBtn ? 370 : 95" :min-width="showCancelBtn ? 95 : 370" @click="handleSubmit" :loading="loading">确认修改</v-btn>
+      <v-btn v-if="props.showCancelBtn" class="mr-5" color="primary" variant="outlined" @click="handleClose">取 消</v-btn>
+      <v-btn color="primary" :max-width="props.showCancelBtn ? 370 : 95" :min-width="props.showCancelBtn ? 95 : 370" @click="handleSubmit" :loading="loading">确认修改</v-btn>
     </div>
   </div>
+  <div class="VerifyBox">
+  </div>
 </template>
 
 <script setup>
@@ -105,6 +107,7 @@ const handleSubmit = async () => {
     password: query.password,
     code: phoneRef.value.loginData.code
   }
+
   // 重置密码需要手机号
   if (props.isReset) data.phone = phoneRef.value.loginData.phone
   loading.value = true
@@ -117,6 +120,7 @@ const handleSubmit = async () => {
     handleClose()
   }
 }
+
 </script>
 
 <style scoped lang="scss">

+ 75 - 11
src/views/login/components/editPasswordEnt.vue

@@ -1,5 +1,5 @@
 <template>
-  <div>
+  <div class="mt-3">
     <v-form ref="emailRef" style="width: 100%;">
       <v-text-field
         v-model="query.email"
@@ -21,7 +21,8 @@
         :rules="[v=> !!v || '请输入邮箱收到的验证码']"
       >
         <template #append-inner>
-          <span class="login-code" @click="handleCode">{{ $t('login.getSmsCode') }}</span>
+          <span v-if="showCode" class="login-code" @click="handleCode">{{ $t('login.getSmsCode') }}</span>
+          <span v-else class="disable">{{ $t('login.retrieveAgain') }}{{ count }}s</span>
         </template>
       </v-text-field>
     </v-form>
@@ -57,6 +58,14 @@
       <v-btn color="primary" style="width: 100%;" @click="handleSubmit" :loading="loading">确认修改</v-btn>
     </div>
   </div>
+  <Verify
+    v-if="props.openVerify"
+    ref="entEditPasswordVerify"
+    captchaType="blockPuzzle"
+    :imgSize="{ width: '400px', height: '200px' }"
+    mode="pop"
+    @success="verifySuccess"
+  />
 </template>
 
 <script setup>
@@ -65,17 +74,19 @@ import { ref, reactive, computed } from 'vue'
 import { entResetPassword, getEmailCode } from '@/api/common/index'
 import Snackbar from '@/plugins/snackbar'
 import { checkEmail } from '@/utils/validate'
+import Verify from '@/components/Verifition'
+import { setCodeTime } from '@/utils/code'
 import { useRouter } from 'vue-router'; const router = useRouter()
 
-const emit = defineEmits(['cancel', 'getCode'])
+// const emit = defineEmits(['cancel'])
 const props = defineProps({
   phone: {
     type: String,
     default: ''
   },
-  captchaVerification: {
-    type: String,
-    default: ''
+  openVerify: { // 是否开启人机验证
+    type: Boolean,
+    default: false
   },
   showCancelBtn: {
     type: Boolean,
@@ -122,28 +133,58 @@ const confirmPassword = computed(() => {
 //   emit('cancel')
 // }
 
+
+const showCode = ref(true)
+const count = ref(0)
+const timer = ref(null)
 const handleCode = async () => {
   if (!query.email || !checkEmail(query.email)) {
     Snackbar.warning('请输入企业邮箱')
     return
   }
-  emit('getCode')
+  if (props.openVerify && !captchaVerification.value) {
+    getCode()
+    return
+  }
   await getEmailCode(query.email)
+  count.value = 60
+  setTime()
   Snackbar.success('已发送验证码,请注意查看!')
 }
 
+const setTime = () => {
+  showCode.value = false
+  timer.value = setInterval(() => {
+    let number = count.value
+    if (number > 0 && number <= 60) {
+      count.value--
+      setCodeTime(number - 1)
+    } else {
+      showCode.value = true
+      clearInterval(timer.value)
+      timer.value = null
+    }
+  }, 1000)
+}
+const autoTimer = () => {
+  count.value = 0
+  if(!count.value) return
+  setTime()
+}
+autoTimer()
+
 // 修改
 const handleSubmit = async () => {
   const emailValid = await emailRef.value.validate()
   const passwordValid = await passwordRef.value.validate()
   if (!emailValid.valid || !passwordValid.valid) return
-  if (!props.captchaVerification) {
-    emit('getCode')
+  if (!captchaVerification.value) {
+    getCode()
     return
   }
   const data = {
     ...query,
-    captchaVerification: props.captchaVerification,
+    captchaVerification: captchaVerification.value,
   }
   loading.value = true
   // const api = props.isReset ? resetPassword : updatePassword
@@ -153,12 +194,26 @@ const handleSubmit = async () => {
     setTimeout(() => {
       router.push({ path: '/login', query: { entLogin: true } })
     }, 1000);
+  } catch (error) {
+    Snackbar.warning(error?.msg || error)
   } finally {
     loading.value = false
-    // handleClose()
   }
 }
 
+
+// 获取验证码
+const entEditPasswordVerify = ref()
+const getCode = async () => {
+  // 弹出验证码 // 已开启:则展示验证码;只有完成验证码的情况,才进行登录
+  entEditPasswordVerify.value.show()
+}
+
+const captchaVerification = ref(false)
+const verifySuccess = (params) => {
+  captchaVerification.value = params.captchaVerification
+  handleCode()
+}
 </script>
 
 <style scoped lang="scss">
@@ -169,4 +224,13 @@ const handleSubmit = async () => {
   font-size: 12px; 
   cursor: pointer;
 }
+.disable {
+  width: 72px;
+  color: grey;
+  font-size: 12px;
+}
+.phone-number {
+  width: 34px;
+  font-size: 12px;
+}
 </style>

+ 3 - 4
src/views/login/forgotPassword.vue

@@ -47,12 +47,11 @@ onMounted(() => {
   height: 100%;
   background-image: url('https://minio.menduner.com/dev/menduner/login-bgc.jpg');
   background-size: cover;
+  display: flex;
+  justify-content: center;
+  align-items: center;
 }
 .content {
-  position: absolute;
-  top: 50%;
-  left: 50%;
-  translate: -50% -50%;
   width: 450px;
   height: 450px;
   background-color: #fff;

+ 5 - 27
src/views/login/forgotPasswordEnt.vue

@@ -5,7 +5,7 @@
       <div class="resume-header">
         <div class="resume-title">企业修改密码</div>
       </div>
-      <editPasswordPage class="mt-5" :showCancelBtn="false" :captchaVerification="captchaVerification" @getCode="getCode"  @cancel="router.push('/login')">
+      <editPasswordPage :showCancelBtn="false" openVerify @cancel="router.push('/login')">
         <template #custom>
           <div class="font-size-14 text-end">
             <span class="color-primary cursor-pointer" @click="router.push('/login')">回到登录页</span>
@@ -14,13 +14,6 @@
       </editPasswordPage>
     </div>
   </div>
-  <Verify
-    ref="verify"
-    captchaType="blockPuzzle"
-    :imgSize="{ width: '400px', height: '200px' }"
-    mode="pop"
-    @success="verifySuccess"
-  />
 </template>
 
 <script setup>
@@ -28,7 +21,6 @@ defineOptions({ name: 'forgotPasswordEnt'})
 import { useRouter } from 'vue-router'
 import navBar from '@/layout/personal/navBar.vue'
 import editPasswordPage from '@/views/login/components/editPasswordEnt.vue'
-import Verify from '@/components/Verifition'
 import { ref, onMounted } from 'vue'
 
 const router = useRouter()
@@ -39,19 +31,6 @@ onMounted(() => {
   isMobile.value = /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i.test(userAgent)
 })
 
-// 验证码
-const verify = ref()
-
-// 获取验证码
-const getCode = async () => {
-  // 弹出验证码 // 已开启:则展示验证码;只有完成验证码的情况,才进行登录
-  verify.value.show()
-}
-
-const captchaVerification = ref(false)
-const verifySuccess = (params) => {
-  captchaVerification.value = params.captchaVerification
-}
 </script>
 
 <style scoped lang="scss">
@@ -66,13 +45,12 @@ const verifySuccess = (params) => {
   height: 100%;
   background-image: url('https://minio.menduner.com/dev/menduner/login-bgc.jpg');
   background-size: cover;
+  display: flex;
+  justify-content: center;
+  align-items: center;
 }
 .content {
-  position: absolute;
-  top: 50%;
-  left: 50%;
-  translate: -50% -50%;
-  width: 500px;
+  width: 450px;
   height: 450px;
   background-color: #fff;
   border-radius: 10px;

+ 12 - 13
src/views/login/index.vue

@@ -30,7 +30,7 @@
             <v-window v-model="tab">
                 <!-- 验证码登录 -->
               <v-window-item :value="1">
-                <phoneFrom ref="phoneRef" :openCaptcha="true" :captchaStr="captchaStr" @getCaptchaStr="getCode" @handleEnter="handleLogin"></phoneFrom>
+                <phoneFrom ref="phoneRef" openVerify @handleEnter="handleLogin"></phoneFrom>
               </v-window-item>
                 <!-- 账号密码登录 -->
               <v-window-item :value="2">
@@ -138,10 +138,6 @@ const handleLogin = async () => {
   const { valid } = isEnterpriseLogin.value ? await entPassRef.value.passwordForm.validate() : tab.value === 1 ? await phoneRef.value.phoneForm.validate() : await passRef.value.passwordForm.validate()
   if (!valid) return
   if (!isAgree.value) return Snackbar.warning('请阅读并勾选底部协议')
-  if (!captchaStr.value) {
-    getCode() // 验证码组件
-    return
-  }
   
   loginLoading.value = true
   try {
@@ -150,7 +146,11 @@ const handleLogin = async () => {
     // else { params = { ...passRef.value.loginData }; api = 'handlePasswordLogin'}
     if (isEnterpriseLogin.value) { params = { ...entPassRef.value.loginData }; api = 'handlePasswordLogin'}
     else { params = tab.value === 1 ? { ...phoneRef.value.loginData } : { ...passRef.value.loginData }; api = tab.value === 1 ? 'handleSmsLogin' : 'handlePasswordLogin'}
-    if (captchaStr.value) params.captchaVerification = captchaStr.value // 人机验证
+    if (!params.captchaVerification && captchaStr.value) params.captchaVerification = captchaStr.value
+    if (!params.captchaVerification) {
+      getCode() // 验证码组件
+      return
+    }
 
     // 邮箱为企业招聘, 手机号为个人求职
     if (isEnterpriseLogin.value) {
@@ -218,9 +218,8 @@ const carouselList = ref([
   { src: 'https://minio.menduner.com/dev/menduner/Grand-Mercure.jpg' }
 ])
 
-// 验证码
-const verify = ref()
 // 获取验证码
+const verify = ref()
 const getCode = async () => {
   // 弹出验证码 // 已开启:则展示验证码;只有完成验证码的情况,才进行登录
   verify.value.show()
@@ -229,11 +228,11 @@ const getCode = async () => {
 const captchaStr = ref('')
 const verifySuccess = (params) => {
   captchaStr.value = params.captchaVerification
-  if (!isEnterpriseLogin.value && tab.value === 1 && phoneRef.value) {
-    nextTick(() => { phoneRef.value.handleCode() }) // 在获取验证码之前加人机验证
-  } else {
-    handleLogin()
-  }
+  // if (!isEnterpriseLogin.value && tab.value === 1 && phoneRef.value) {
+  //   nextTick(() => { phoneRef.value.handleCode() }) // 在获取验证码之前加人机验证
+  // } else {
+  // }
+  handleLogin()
 }
 
 </script>

+ 19 - 5
src/views/recruit/personal/PersonalCenter/accountSettings/editPassword.vue

@@ -7,7 +7,14 @@
       <span>{{ userInfo.phone }}</span>
       <span class="color-primary ml-5 text-decoration-underline cursor-pointer" @click="showEdit = true">修改密码</span>
     </div>
-    <editPasswordPage v-if="showEdit" :phone="userInfo.phone" @cancel="showEdit = false" class="editPage"></editPasswordPage>
+    <div class="editPageBox">
+      <editPasswordPage
+        v-if="showEdit"
+        :phone="userInfo.phone"
+        @cancel="showEdit = false"
+        class="editPage"
+      ></editPasswordPage>
+    </div>
   </div>
 </template>
 
@@ -32,10 +39,17 @@ h3 {
   color: var(--color-666);
   font-weight: 600;
 }
+.editPageBox {
+  width: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
 .editPage {
-  position: absolute;
-  top: 50%;
-  left: 50%;
-  transform: translate(-50%, -50%);
+  // display: flex;
+  // justify-content: center;
+  // align-items: center;
+  width: 450px;
+  height: 450px;
 }
 </style>

+ 11 - 32
src/views/register/person.vue

@@ -3,7 +3,9 @@
     <navBar v-if="!isMobile" :showLoginBtn="false" class="navBar"></navBar>
     <div class="content pa-10">
       <div class="content-title text-center mt-4">{{ isLogin ? '请输入您申请企业账号时填入的手机号进行效验' : '请输入手机号码进行注册认证'}}</div>
-      <phoneFrom class="mt-10" ref="phoneRef" :openCaptcha="true" :captchaStr="captchaStr" @getCaptchaStr="getCode" @handleEnter="handleRegister" :phone="phone"></phoneFrom>
+      <div class="mt-10">
+        <phoneFrom ref="phoneRef" openVerify @handleEnter="handleRegister" :phone="phone"></phoneFrom>
+      </div>
       <div v-if="!isMobile" class="font-size-14 tips color-primary cursor-pointer text-end" @click="router.push('/login')">已有账号?去登录</div>
       <v-btn :loading="loading" color="primary" class="white--text mt-5" min-width="370" @click="handleRegister">{{ isCompany ? '下一步' : '注册' }}</v-btn>
       <div class="login-tips mt-3" v-if="!isCompany">
@@ -15,13 +17,6 @@
       </div>
     </div>
   </div>
-  <Verify
-    ref="verify"
-    captchaType="blockPuzzle"
-    :imgSize="{ width: '400px', height: '200px' }"
-    mode="pop"
-    @success="verifySuccess"
-  />
 </template>
 
 <script setup>
@@ -33,7 +28,6 @@ import { useUserStore } from '@/store/user'
 import Snackbar from '@/plugins/snackbar'
 import { checkEmail } from '@/utils/validate'
 import navBar from '@/layout/personal/navBar.vue'
-import Verify from '@/components/Verifition'
 
 const isMobile = ref(false)
 onMounted(() => {
@@ -60,28 +54,11 @@ const isAgree = ref(false)
 const userStore = useUserStore()
 const phone = localStorage.getItem('loginAccount') && !checkEmail(localStorage.getItem('loginAccount')) ? localStorage.getItem('loginAccount') : ''
 
-// 验证码
-const verify = ref()
-// 获取验证码
-const getCode = async () => {
-  // 弹出验证码 // 已开启:则展示验证码;只有完成验证码的情况,才进行登录
-  verify.value.show()
-}
-const captchaStr = ref('')
-const verifySuccess = (params) => {
-  captchaStr.value = params.captchaVerification
-  phoneRef.value.handleCode()
-}
-
 // 注册
 const handleRegister = async () => {
   const { valid } = await phoneRef.value.phoneForm.validate()
   if (!valid) return
-  if (!isAgree.value) return Snackbar.warning('请阅读并勾选底部协议')
-  if (!captchaStr.value) {
-    getCode() // 验证码组件
-    return
-  }
+  if (!props.isCompany && !isAgree.value) return Snackbar.warning('请阅读并勾选底部协议')
   loading.value = true
   try {
     // isLogin:企业注册申请被驳回后,再次提交时需先登录个人账号
@@ -112,16 +89,18 @@ const handleRegister = async () => {
   height: 100%;
   background-image: url('https://minio.menduner.com/dev/menduner/login-bgc.jpg');
   background-size: cover;
+  display: flex;
+  justify-content: center;
+  align-items: center;
 }
 .content {
-  position: absolute;
-  top: 50%;
-  left: 50%;
-  translate: -50% -50%;
   width: 450px;
-  height: 400px;
+  height: 450px;
   background-color: #fff;
   border-radius: 10px;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
   &-title {
     color: #4c4c4c;
     font-size: 24px;