美文网首页
Vue3 & TypeScript ---- 记住密码 + 获取

Vue3 & TypeScript ---- 记住密码 + 获取

作者: 牛会骑自行车 | 来源:发表于2023-04-18 11:56 被阅读0次
效果图: 登录页面效果图
功能:

. 账号登录、验证码登录;
. 账号登录:记住密码。使用aes和ras给用户数据加密储存于localStorage;
. 验证码登录:手机号码为空时,获取验证码按钮为禁用状态;获取验证码按钮在成功点击后会启动倒计时,并同时转为禁用状态。

登录页代码:
<template>
  <div class="login-frame">
    <div class="login-body">
      <NjxSwitchTab :list="tabList" @switch-tab="({index}) => tabActive = index" />
      <div class="form-view">
        <el-form v-if="tabActive === 0" size="large" ref="formCodeRef" :model="formCode" :rules="rulesCode">
          <el-form-item prop="phone">
            <el-input class="form-item" clearable :prefix-icon="User" v-model="formCode.phone" placeholder="请输入手机号码"
              type="number" @keyup.enter="handleFocus(passwordRef)"></el-input>
          </el-form-item>
          <el-form-item prop="password">
            <el-input class="form-item" :prefix-icon="Lock" v-model="formCode.password" placeholder="请输入密码" show-password @keyup.enter="handleLogin(formCodeRef)"
              clearable ref="passwordRef"></el-input>
          </el-form-item>
        </el-form>
        <el-form v-else size="large" ref="formVerifyRef" :model="formVerify" :rules="rulesVerify">
          <el-form-item prop="phone">
            <el-input type="number" class="form-item" v-model="formVerify.phone" placeholder="请输入手机号码" clearable :prefix-icon="Lock" @keyup.enter="handleFocus(verifyRef)"></el-input>
          </el-form-item>
          <el-form-item prop="verifyCode">
            <el-input class="form-item" placeholder="请输入验证码" v-model="formVerify.verifyCode" ref="verifyRef" @keyup.enter="handleLogin(formVerifyRef)">
              <template #append>
                <el-button type="primary" @click="getVerifyCode" :disabled="disabledVerify">{{ verify.buttonText
                }}</el-button>
              </template>
            </el-input>
          </el-form-item>
        </el-form>
        <div class="form-operation clearboth">
          <el-checkbox v-model="rememberPassword" label="记住密码" class="float_l" v-if="tabActive === 0" />
          <div class="float_r" v-if="false">
            <el-button type="primary" link>忘记密码</el-button>
            <el-button type="primary" link>免费注册</el-button>
          </div>
        </div>
        <el-button size="large" :disabled="disabledLoginButton" type="primary" class="w_100"
          @click="handleLogin(tabActive === 0 ? formCodeRef : formVerifyRef)">登录</el-button>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { User, Lock } from "@element-plus/icons-vue";
import { FormInstance, FormRules } from "element-plus";
import Router from "@/router"
import { validMobile, validPassword } from "@/utils/utils"
import {njxEncode, njxDecode} from "@/utils/ancode"

// 账号登录
const formCode = ref({
  phone: "",
  password: "",
});
const validPhone = (rule: any, value: string, callback: any) => {
  if (!value) {
    return callback(new Error("请输入电话号码"));
  } else if (!validMobile(value)) {
    return callback(new Error("请输入真实手机号码"));
  } else {
    callback();
  }
}
const validPswd = (rule: any, value: string, callback: any) => {
  if (!value) {
    return callback(new Error("请输入密码"));
  } else if (!validPassword(value)) {
    return callback(new Error("请输入6~14位包含字母和数字的密码"))
  } else {
    callback();
  }
}
const rulesCode = reactive<FormRules>({
  phone: [{ required: true, trigger: "blur", validator: validPhone }],
  password: [{ required: true, trigger: "blur", validator: validPswd }],
})
// 验证码登录
const formVerify = ref({
  phone: "",
  verifyCode: ""
})
const rulesVerify = reactive<FormRules>({
  phone: [{ required: true, trigger: "blur", validator: validPhone }],
  verifyCode: [{ required: true, trigger: "blur", message: "请输入验证码" }]
})

const formCodeRef = ref<FormInstance>();
const formVerifyRef = ref<FormInstance>();
const passwordRef = ref()
const verifyRef = ref();

const rememberPassword = ref(false);
const disabledLoginButton = computed(() => {
  const tab1 = !formCode.value.phone || !formCode.value.password;
  const tab2 = !formVerify.value.phone || !formVerify.value.verifyCode;

  return tabActive.value === 0 ? tab1 : tab2;
})

const handleLogin = (formEl: FormInstance | undefined) => {
  if(!formEl) return;
  formEl.validate((valid) => {
    if(!valid) return;
    ElNotification({
      title: "登录成功~~立即跳转首页。账号: ",
      message: tabActive.value === 0 ? formCode.value.phone : formVerify.value.phone,
    })
    // 记住密码
    if(rememberPassword.value) {
      const params = tabActive.value === 0 ? JSON.stringify(formCode.value) : JSON.stringify(formVerify);
      const {key, data} = njxEncode(params);
      localStorage.setItem("NJX_LOGININFO_KEY", key);
      localStorage.setItem("NJX_LOGININFO_CONTENT", data);
    } 
    setTimeout(() => {
      Router.push("/")
    }, 1400)
  })
};

// 切换登录方式
const tabActive = ref(0);
const tabList = [
  {
    label: "账号登录",
  },
  {
    label: "验证码登录",
  },
];

const handleFocus = (formEl: any) => {
  if (!formEl) return;
  formEl.focus();
}


// 验证码
const resetCount = () => {
  clearInterval(timer);
  timer = 0;
};

let timer: number = 0;
const verify = reactive({
  count: 11,
  buttonText: "获取验证码",
});
const disabledVerify = computed(() => {
  return !formVerify.value.phone || verify.count <= 10;
});
const getVerifyCode = () => {
  // 校验手机号码
  if(!validMobile(formVerify.value.phone)) return;
  ElMessage.success("验证码发送成功,请查看");

  verify.count--;
  verify.buttonText = verify.count + " 秒后重新获取验证码";
  timer = window.setInterval(() => {
    if (verify.count <= 1) {
      resetCount();
      verify.buttonText = "重新发送验证码";
      verify.count = 11;
      return;
    }
    verify.count--;
    verify.buttonText = verify.count + " 秒后重新获取验证码";
  }, 1000);
};

const handleRemember = () => {
  const clearStorage = () => {
    localStorage.removeItem("NJX_LOGININFO_KEY");
    localStorage.removeItem("NJX_LOGININFO_CONTENT");
    rememberPassword.value = false;
  }

  const content = localStorage.getItem("NJX_LOGININFO_CONTENT");
  const key = localStorage.getItem("NJX_LOGININFO_KEY");
  
  // 没有保存内容
  if(!content || !key) {
    clearStorage();
    return;
  };
  const {res} = njxDecode(content, key);
  if(!res) {
    clearStorage();
  } else {
    formCode.value = JSON.parse(res);
    rememberPassword.value = true;
  }
}


onMounted(() => {
  resetCount();
  handleRemember();
});
</script>

<style lang="scss" scoped>
.login-frame {
  width: 320px;
  height: 100%;

  margin: auto;
}

.login-body {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.form-view {
  width: 100%;
  height: 200px;
}

.form-item {
  margin-top: 20px;
}

.form-operation {
  height: 50px;
  line-height: 50px;
}

.el-input-group__append button.el-button {
  color: $primary;
}

.el-input-group__append button.el-button.is-disabled {
  color: #c1c1c1 !important;
}

.el-form-item--large {
  margin-bottom: 0;
}
</style>
加解密代码请查看 vue ---- 使用rsa和aes给接口加解密

tada~~~一个有“记住密码”和“获取验证码”的登录页面就完成啦~

相关文章

网友评论

      本文标题:Vue3 & TypeScript ---- 记住密码 + 获取

      本文链接:https://www.haomeiwen.com/subject/rqvhjdtx.html