feat: 增加忘记密码
							parent
							
								
									ce41faacc5
								
							
						
					
					
						commit
						edfe5a56e2
					
				| 
						 | 
				
			
			@ -26,6 +26,9 @@ declare module 'vue' {
 | 
			
		|||
    ASwitch: typeof import('ant-design-vue/es')['Switch']
 | 
			
		||||
    ATextarea: typeof import('ant-design-vue/es')['Textarea']
 | 
			
		||||
    ATooltip: typeof import('ant-design-vue/es')['Tooltip']
 | 
			
		||||
    ElButton: typeof import('element-plus/es')['ElButton']
 | 
			
		||||
    ElDialog: typeof import('element-plus/es')['ElDialog']
 | 
			
		||||
    ElInput: typeof import('element-plus/es')['ElInput']
 | 
			
		||||
    ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
 | 
			
		||||
    Empty: typeof import('./src/components/empty/Empty.vue')['default']
 | 
			
		||||
    ImageCropper: typeof import('./src/components/image-cropper/index.vue')['default']
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,12 +21,12 @@ export function logout() {
 | 
			
		|||
}
 | 
			
		||||
export function getConfig(params) {
 | 
			
		||||
  return request.get('/sms/v1/logo', {
 | 
			
		||||
    params: wrapperParams(params),
 | 
			
		||||
    params: wrapperParams(params)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
export function getDict(data) {
 | 
			
		||||
  return request.get('/dict/children', {
 | 
			
		||||
    params: wrapperParams(data),
 | 
			
		||||
    params: wrapperParams(data)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
export function getSysconf() {
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +48,7 @@ export function getPortal(params) {
 | 
			
		|||
}
 | 
			
		||||
export function getServiceQuota(tenantId, data) {
 | 
			
		||||
  return request.get(`/cos/v1/tenants/${tenantId}/quotas`, {
 | 
			
		||||
    params: wrapperParams(data),
 | 
			
		||||
    params: wrapperParams(data)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
export function replaceToken(params) {
 | 
			
		||||
| 
						 | 
				
			
			@ -69,7 +69,7 @@ export function getSystemTreeConfigs(params) {
 | 
			
		|||
// 更新系统配置信息
 | 
			
		||||
export function updateSystemConfigs(params) {
 | 
			
		||||
  return request.put('/sms/v1/system-configs', params, {
 | 
			
		||||
    headers: { 'Content-Type': 'multipart/form-data', BsmAjaxHeader: true, options: { noSeri: true } },
 | 
			
		||||
    headers: { 'Content-Type': 'multipart/form-data', BsmAjaxHeader: true, options: { noSeri: true } }
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
// 测试连接
 | 
			
		||||
| 
						 | 
				
			
			@ -79,3 +79,8 @@ export function testLinkApi(category) {
 | 
			
		|||
export function getVertifyCode(params) {
 | 
			
		||||
  return request.post('/sms/v1/users/code', wrapperParams(params))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 忘记密码
 | 
			
		||||
export function forgetPassword(params) {
 | 
			
		||||
  return request.post('/sms/v1/users/forget', params)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,13 +42,42 @@
 | 
			
		|||
              <a-switch v-model:checked="remember"></a-switch>
 | 
			
		||||
              <span class="m-l-xs">记住密码</span>
 | 
			
		||||
            </span>
 | 
			
		||||
            <a :href="`mailto:${configs.helpInformationLink}`" type="text" class="text-info pull-right help-info" :title="configs.helpInformationContent">{{ configs.helpInformationContent }}</a>
 | 
			
		||||
            <a :href="`mailto:${configs.helpInformationLink}`" type="text" class="text-info help-info" :title="configs.helpInformationContent">{{ configs.helpInformationContent }}</a>
 | 
			
		||||
            <a type="text" class="m-l text-info forgot-password" @click="openForgotPasswordDialog">忘记密码</a>
 | 
			
		||||
          </div>
 | 
			
		||||
        </a-form-item>
 | 
			
		||||
        <a-button class="login-btn" type="primary" size="medium" :loading="loading" @click="handleLogin">登录</a-button>
 | 
			
		||||
      </a-form>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="copyright-info">{{ configs.copyrightInformation }}</div>
 | 
			
		||||
    <!-- 忘记密码弹窗 -->
 | 
			
		||||
    <a-modal title="忘记密码" v-model:visible="showForgotPasswordDialog" width="600px" :confirm-loading="forgotPasswordLoading" @ok="handleForgotPassword" :close-on-click-modal="false">
 | 
			
		||||
      <a-form :model="forgotPasswordForm" ref="forgotPasswordFormRef" label-position="left" :labelCol="{ style: { width: '80px' } }">
 | 
			
		||||
        <a-form-item label="用户名" name="account" :rules="[{ ...required, message: '请输入用户名' }]">
 | 
			
		||||
          <a-input class="w-lg" v-model:value="forgotPasswordForm.account" placeholder="请输入用户名"></a-input>
 | 
			
		||||
        </a-form-item>
 | 
			
		||||
        <a-form-item label="新密码" name="password" :rules="[{ ...required, message: '请输入密码' }]">
 | 
			
		||||
          <a-input class="w-lg" v-model:value="forgotPasswordForm.password" type="password" placeholder="请输入新密码" show-password></a-input>
 | 
			
		||||
        </a-form-item>
 | 
			
		||||
        <a-form-item label="确认密码" name="confirmPassword" :rules="[{ ...required, message: '请输入密码' }]">
 | 
			
		||||
          <a-input class="w-lg" v-model:value="forgotPasswordForm.confirmPassword" type="password" placeholder="请再次输入新密码" show-password></a-input>
 | 
			
		||||
        </a-form-item>
 | 
			
		||||
        <a-form-item label="验证码" name="verificationCode" :rules="[{ ...required, message: '请输入验证码' }]">
 | 
			
		||||
          <div class="verification-code-input">
 | 
			
		||||
            <a-input class="w-lg m-r" v-model:value="forgotPasswordForm.verificationCode" placeholder="请输入验证码"></a-input>
 | 
			
		||||
            <a-button type="primary" :disabled="codeCountdown > 0" @click="getVerificationCode" :loading="codeLoading">
 | 
			
		||||
              {{ codeCountdown > 0 ? `${codeCountdown}s后重新获取` : '获取验证码' }}
 | 
			
		||||
            </a-button>
 | 
			
		||||
          </div>
 | 
			
		||||
        </a-form-item>
 | 
			
		||||
      </a-form>
 | 
			
		||||
      <template #footer>
 | 
			
		||||
        <div class="dialog-footer">
 | 
			
		||||
          <a-button @click="showForgotPasswordDialog = false">取消</a-button>
 | 
			
		||||
          <a-button type="primary" :loading="forgotPasswordLoading" @click="handleForgotPassword">确定</a-button>
 | 
			
		||||
        </div>
 | 
			
		||||
      </template>
 | 
			
		||||
    </a-modal>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -61,8 +90,8 @@ import { useStore } from 'vuex'
 | 
			
		|||
import { useRouter, useRoute } from 'vue-router'
 | 
			
		||||
import setLoginData from './tools'
 | 
			
		||||
import { required } from '@/validate'
 | 
			
		||||
import { getVertifyCode } from '@/services'
 | 
			
		||||
import { message } from 'ant-design-vue'
 | 
			
		||||
import { getVertifyCode, forgetPassword } from '@/services'
 | 
			
		||||
import { message, Modal } from 'ant-design-vue'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  components: { UserOutlined, LockOutlined },
 | 
			
		||||
| 
						 | 
				
			
			@ -78,11 +107,23 @@ export default {
 | 
			
		|||
      verifyLoading: false,
 | 
			
		||||
      countdown: 0,
 | 
			
		||||
      isCountingDown: false,
 | 
			
		||||
      needSmsVerify: true
 | 
			
		||||
      needSmsVerify: true,
 | 
			
		||||
      showForgotPasswordDialog: false,
 | 
			
		||||
      forgotPasswordForm: {
 | 
			
		||||
        account: '',
 | 
			
		||||
        password: '',
 | 
			
		||||
        confirmPassword: '',
 | 
			
		||||
        verificationCode: ''
 | 
			
		||||
      },
 | 
			
		||||
      forgotPasswordLoading: false,
 | 
			
		||||
      codeCountdown: 0,
 | 
			
		||||
      codeLoading: false
 | 
			
		||||
    })
 | 
			
		||||
    const store = useStore()
 | 
			
		||||
    const pwdRule = computed(() => store.state.app.systemConfig.pwdStrength + ',pswNoSpace' + ',required')
 | 
			
		||||
    const configs = computed(() => store.getters.pageConfig)
 | 
			
		||||
    const loginFormRef = ref(null)
 | 
			
		||||
    const forgotPasswordFormRef = ref(null)
 | 
			
		||||
    let countdownTimer = null
 | 
			
		||||
 | 
			
		||||
    // 开始倒计时
 | 
			
		||||
| 
						 | 
				
			
			@ -122,12 +163,15 @@ export default {
 | 
			
		|||
    const route = useRoute()
 | 
			
		||||
 | 
			
		||||
    // 监听account变化,如果清空则重置needSmsVerify
 | 
			
		||||
    watch(() => state.loginForm.account, (newAccount) => {
 | 
			
		||||
      if (!newAccount.trim()) {
 | 
			
		||||
        state.needSmsVerify = true
 | 
			
		||||
        resetCountdown() // 同时重置倒计时
 | 
			
		||||
    watch(
 | 
			
		||||
      () => state.loginForm.account,
 | 
			
		||||
      (newAccount) => {
 | 
			
		||||
        if (!newAccount.trim()) {
 | 
			
		||||
          state.needSmsVerify = true
 | 
			
		||||
          resetCountdown() // 同时重置倒计时
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    const getVertify = () => {
 | 
			
		||||
      if (state.isCountingDown) return // 如果正在倒计时,不允许重复点击
 | 
			
		||||
| 
						 | 
				
			
			@ -209,6 +253,58 @@ export default {
 | 
			
		|||
        state.capsTooltip = false
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getVerificationCode() {
 | 
			
		||||
      if (!state.forgotPasswordForm.account) {
 | 
			
		||||
        message.error('请先输入用户名')
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
      state.codeLoading = true
 | 
			
		||||
      getVertifyCode({ account: state.forgotPasswordForm.account })
 | 
			
		||||
        .then((res) => {
 | 
			
		||||
          if (res.success) {
 | 
			
		||||
            message.success('验证码已发送')
 | 
			
		||||
            state.codeCountdown = 60
 | 
			
		||||
            const timer = setInterval(() => {
 | 
			
		||||
              state.codeCountdown--
 | 
			
		||||
              if (state.codeCountdown <= 0) {
 | 
			
		||||
                clearInterval(timer)
 | 
			
		||||
              }
 | 
			
		||||
            }, 1000)
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
        .finally(() => {
 | 
			
		||||
          state.codeLoading = false
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function openForgotPasswordDialog() {
 | 
			
		||||
      // 将当前登录表单的用户名带入忘记密码表单
 | 
			
		||||
      state.forgotPasswordForm.account = state.loginForm.account
 | 
			
		||||
      state.showForgotPasswordDialog = true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function handleForgotPassword() {
 | 
			
		||||
      forgotPasswordFormRef.value.validate().then(() => {
 | 
			
		||||
        const { account, password, confirmPassword, verificationCode } = state.forgotPasswordForm
 | 
			
		||||
        if (confirmPassword !== password) return message.error('两次输入的密码不相同')
 | 
			
		||||
        state.forgotPasswordLoading = true
 | 
			
		||||
        forgetPassword({
 | 
			
		||||
          account,
 | 
			
		||||
          password: encrypt(password),
 | 
			
		||||
          code: verificationCode
 | 
			
		||||
        })
 | 
			
		||||
          .then((res) => {
 | 
			
		||||
            if (res.success) {
 | 
			
		||||
              message.success(res.message)
 | 
			
		||||
              state.showForgotPasswordDialog = false
 | 
			
		||||
            }
 | 
			
		||||
          })
 | 
			
		||||
          .finally(() => {
 | 
			
		||||
            state.forgotPasswordLoading = false
 | 
			
		||||
          })
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
      ...toRefs(state),
 | 
			
		||||
      required,
 | 
			
		||||
| 
						 | 
				
			
			@ -218,7 +314,12 @@ export default {
 | 
			
		|||
      checkCapslock,
 | 
			
		||||
      getVertify,
 | 
			
		||||
      startCountdown,
 | 
			
		||||
      resetCountdown
 | 
			
		||||
      resetCountdown,
 | 
			
		||||
      forgotPasswordFormRef,
 | 
			
		||||
      getVerificationCode,
 | 
			
		||||
      openForgotPasswordDialog,
 | 
			
		||||
      handleForgotPassword,
 | 
			
		||||
      pwdRule
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue