index.vue 9.55 KB
<template>
  <div>
    <DialogPlus modal-class="auth-user" append-to-body v-model="dialogVisible" @open="openedDialog" width="460px"
      maxHeight="250px" :close-on-click-modal="false" title="用户身份认证">
      <div class="select-tenant">
        <el-form v-show="formType == 'validate'" label-position="top" ref="registerFormRef" :model="registerForm"
          :rules="registerRules" class="login-form" auto-complete="on">
          <el-form-item prop="logonUser" label="账号">
            <el-input v-model.trim="registerForm.logonUser" :disabled="isModifypassword" placeholder="请输入账号" text tabindex="1" autocomplete="on">
            </el-input>
          </el-form-item>
          <el-form-item prop="mobileNo" label="手机号">
            <el-input v-model.trim="registerForm.mobileNo" :disabled="isModifypassword" placeholder="请输入手机号" text tabindex="1" autocomplete="on">
            </el-input>
          </el-form-item>
          <el-form-item prop="validateCode" label="图形验证码">
            <el-input class="captcha" v-model.trim="registerForm.validateCode" placeholder="请输入图形验证码" tabindex="2"
              autocomplete="on">
              <template #append>
                <img class="h-26px" :src="imgCaptchaBase64" @click="refreshPictureCode" />
              </template>
            </el-input>
          </el-form-item>
        </el-form>
        <el-form v-show="formType === 'reset'" label-position="top" ref="resetFormRef" :model="resetForm" :rules="resetRules"
          autocomplete="off" class="login-form" auto-complete="on">
          <el-form-item prop="smsCode" autocomplete="off" label="短信验证码">
            <el-input v-model.trim="resetForm.smsCode" autocomplete="off" name="captcha-unique123"
              :placeholder="`请输入${registerForm.mobileNo.substring(0, 3)}****${registerForm.mobileNo.substring(7)}收到的短信验证码`">
              <template #append>
                <span>{{ `${timeLeft}s` }}</span>
              </template>
            </el-input>
            <div class="code-desc">
              <span>若手机未收到验证码,请</span>
              <el-button link type="primary" size="small" @click="recertification"
                style="padding: 0px;vertical-align: baseline;">重新认证</el-button>
            </div>
          </el-form-item>
          <el-form-item prop="pwd" label="新密码" :error="errorPsw">
            <!-- <el-input v-model.trim="resetForm.pwd" type="password" placeholder="请输入新密码" show-password autocomplete="off"
              autocomplete="new-password">
            </el-input> -->
            <PasswordStrengthMeter v-model.trim="password" placeholder="请输入新密码" @change="changePwd" style="width: 100%;"></PasswordStrengthMeter>
          </el-form-item>
          <el-form-item prop="checkPwd" label="确认新密码">
            <el-input v-model.trim="resetForm.checkPwd" type="password" placeholder="请再次输入新密码" show-password
              autocomplete="new-password">
            </el-input>
          </el-form-item>
        </el-form>
      </div>
      <template #footer>
        <el-button @click="closeDialog"> </el-button>
        <el-button v-show="formType === 'validate'" :loading="sendCodeLoading" type="primary"
          @click="handleSendCaptcha">发送验证码至手机</el-button>
        <el-button v-show="formType === 'reset' && timeLeft > 0" :loading="saveLoading" type="primary"
          :disabled="!resetForm.smsCode || !resetForm.pwd || !resetForm.checkPwd"
          @click.prevent="handleReset">修改密码</el-button>
        <el-button v-show="formType === 'reset' && timeLeft == 0" :loading="saveLoading" type="primary"
          @click.prevent="recertification">重新认证</el-button>
      </template>
    </DialogPlus>
  </div>
</template>

<script lang="ts" setup>
import { useValidator } from '@/hooks/useValidator';
import useCountdown from '@/hooks/useCountdown'
import type { FormRules } from 'element-plus'
import { propTypes } from '@/utils/propTypes'
import useIdaasStore from '@/store/modules/idaas';
import {
  getPictureCode
} from "@/api/modules/idaas"
import useLogin from '@/store/modules/login'
import PasswordStrengthMeter from '../PasswordStrengthMeter/index.vue'
import { autoSalt } from '@/utils/common';

// const AsyncPasswordStrengthMeter = defineAsyncComponent(() =>
//   import('../PasswordStrengthMeter/index.vue')
// );

const loginStore = useLogin()
const idaasStore = useIdaasStore()
const { required, phone } = useValidator();
const { proxy } = getCurrentInstance() as any;
const mobileNo = computed(()=> idaasStore.idaasUserInfo.principal?.mobileNo || '')
const logonUser = computed(()=> idaasStore.idaasUserInfo.principal?.logonUser || '')

const props = defineProps({
  schemaInfo: {
    type: Object as PropType<{
      visible: boolean;
    }>,
    default: () => { }
  },
  operate:propTypes.string.def('modifypassword'),
});

const isModifypassword = computed(() => props.operate === 'modifypassword')

const dialogVisible = computed({
  get: () => {
    return props.schemaInfo.visible;
  },
  set: (val) => {
    props.schemaInfo.visible = val
  }
})

function openedDialog() {
  recertification()
  getPictureCodeInfo()
}

function closeDialog() {
  dialogVisible.value = false
}

// 重新认证
const recertification = () => {
  formType.value = 'validate';
  clearForm()
  reset()
}

function clearForm() {
  let _mobileNo = isModifypassword.value ? mobileNo.value : ''
  let _logonUser = isModifypassword.value ? logonUser.value : ''
  password.value = ''
  resetForm.value = {
    smsCode: '',
    pwd: '',
    checkPwd: ''
  }
  registerForm.value = {
    logonUser: _logonUser,
    mobileNo: _mobileNo,
    validateCode: ''
  }
}

// ! 修改密码逻辑
const formType = ref('validate')
const resetFormRef = ref()
const registerFormRef = ref()



const registerRules = ref<FormRules>({
  logonUser: [
    { required: true, trigger: 'blur', message: '请输入账号' },
  ],
  mobileNo: [
    required('请输入手机号'), phone()
  ],
  validateCode: [
    { required: true, trigger: 'blur', message: '请输入图形验证码' },
  ]
})
const registerForm = ref({
  logonUser: '',
  mobileNo: '',
  validateCode: ''
})

function changePwd() {
  resetForm.value.pwd = password.value
}


const errorPsw = computed(() => loginStore.firstUnmetRequirement ? `需要${loginStore.firstUnmetRequirement}` : null)
const password = ref('')
/**
 * 校验新密码
 */
 function validatorPassword(rule, value, callback) {
  console.log(value,loginStore.firstUnmetRequirement);
  if (loginStore.firstUnmetRequirement) {
    callback(new Error(`需要${loginStore.firstUnmetRequirement}`))
  } else {
    callback();
  }
}

/**
 * 校验确认密码
 */
function validatorConfirmpwd(rule, value, callback) {
  if (value != resetForm.value.pwd) {
    callback(new Error('密码不一致,请重新输入'))
  } else {
    callback();
  }
}

const resetRules = ref<FormRules>({
  smsCode: [
    //  不显示验证信息了,只有填写完整,保存按钮才会被使用。
    // {required: true, trigger: 'blur', message: '请输入收到的短信验证码' },
  ],
  pwd: [
    {
      validator: validatorPassword,
      trigger: []
    }
  ],
  checkPwd: [
    {
      validator: validatorConfirmpwd,
      trigger: ['change', 'blur']
    }
  ]
})
const resetForm = ref({
  smsCode: '',
  pwd: '',
  checkPwd: ''
})




let promise: any = ref(null);
/** 图形验证码图片。 */
const imgCaptchaBase64 = ref('');
/** 图形验证码guid */
const validateCodeGuid = ref('');

/** 发送短信验证码的loading */
const sendCodeLoading = ref(false);
/** 重置密码保存的loading */
const saveLoading = ref(false);


const { timeLeft, minutes, seconds, start, stop, reset } = useCountdown(300);
watchEffect(() => {
  console.log(timeLeft.value, 'timeLeft');
  if (timeLeft.value == 0) {
    stop()
  }
})


const refreshPictureCode = () => {
  if (promise.value) {
    return;
  }
  getPictureCodeInfo()
}

function getPictureCodeInfo() {
  promise.value = getPictureCode().then((res: any) => {
    promise.value = null;
    if (res.data.code == proxy.$passCode) {
      imgCaptchaBase64.value = res.data.data?.imageBase64 || "";
      validateCodeGuid.value = res.data.data?.guid || "";
    }
  });
}

const handleSendCaptcha = () => {
  registerFormRef.value && registerFormRef.value.validate((valid) => {
    if (valid) {
      sendCodeLoading.value = true
      let params: any = { ...registerForm.value };
      params.validateCodeGuid = validateCodeGuid.value;
      idaasApi.sendCode(params).then((res: any) => {
        sendCodeLoading.value = false;
        if (res?.data.code == proxy.$passCode) {
          proxy.$ElMessage.success('验证码发送成功!');
          loginStore.firstUnmetRequirement = ''
          formType.value = 'reset';
          resetForm.value.smsCode = '';
          resetForm.value.pwd = "";
          resetForm.value.checkPwd = "";
          start()
        } else {
          refreshPictureCode();
          registerForm.value.validateCode = "";
        }
      });
    }
  });
}

async function handleReset() {
  let res = await resetFormRef.value?.validate()
  if (!res) return
  let params = Object.assign({}, resetForm.value, { mobileNo: registerForm.value.mobileNo, logonUser: registerForm.value.logonUser });
  params.pwd = autoSalt(params.pwd, false, false);
  idaasApi.resetPwd(params).then((res: any) => {
    if (res.data.code == proxy.$passCode) {
      proxy.$ElMessage.success('密码重置成功');
      dialogVisible.value = false;
      userApi.recordUpdateTime(registerForm.value.logonUser)
    }
  });
}


</script>