Newer
Older
KaiFengPC / src / views / login.vue
@zhangdeliang zhangdeliang on 23 May 10 KB 初始化项目
<template>
  <!-- 登录 -->
  <div class="loginPage">
    <!-- 登录表单 -->
    <div class="formCenter">
      <p class="logo">孝感市海绵城市综合管理信息平台</p>
      <el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="loginForm">
        <el-form-item prop="username">
          <el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="请输入账号" :prefix-icon="User"> </el-input>
        </el-form-item>
        <el-form-item prop="password">
          <el-input
            v-model="loginForm.password"
            type="password"
            :prefix-icon="Lock"
            auto-complete="off"
            placeholder="8-20位大小写字母+数字+特殊符号"
            show-password
            @keyup.enter="handleLogin"
          >
          </el-input>
        </el-form-item>
        <el-form-item prop="code" v-if="captchaEnabled" style="display: flex">
          <el-input
            v-model="loginForm.code"
            auto-complete="off"
            placeholder="请输入"
            style="flex: 1"
            @keyup.enter="handleLogin"
            maxlength="8"
          >
          </el-input>
          <div class="login-code">
            <img :src="codeUrl" @click="getCode" />
          </div>
        </el-form-item>
        <el-form-item prop="otp">
          <el-input
            v-model="loginForm.otp"
            type="text"
            :prefix-icon="Lock"
            auto-complete="off"
            placeholder="请输入手机令牌中的令牌"
            @keyup.enter="handleLogin"
          >
          </el-input>
          <p class="appNoneReg" @click="dialogShow = true">手机令牌已注册未扫码?</p>
        </el-form-item>
        <el-checkbox v-model="loginForm.rememberMe" size="large"> 记住密码 </el-checkbox>
        <el-form-item>
          <el-button size="large" @click.prevent="handleLogin" class="loginBtn" :loading="loginLoading">
            <span>登 录</span>
          </el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- 国密注册弹窗 -->
    <el-dialog v-model="dialogShow" title="国密扫码注册" width="500px" append-to-body>
      <div class="guomiRegisterDia">
        <div class="title">
          1,应国密要求,请手机应用商店搜索"手机令牌"并下载之后扫码进行令牌的输入;<br />
          2,请扫描下方二维码完成注册,否则将无法获取手机令牌;
        </div>
        <img :src="qrCodeUrl" alt="" />
      </div>
    </el-dialog>
  </div>
</template>

<script setup>
import { getCodeImg, guomiRegister } from '@/api/login';
import { setToken } from '@/utils/auth';
import Cookies from 'js-cookie';
import { encrypt, decrypt } from '@/utils/jsencrypt';
import { EncryptAES } from '@/utils/AES.js';
import useUserStore from '@/store/modules/user';
import { User, Lock } from '@element-plus/icons-vue';
import usePermissionStore from '@/store/modules/permission';
import axios from 'axios';
import qrcode from 'qrcode'; //生成二维码

const userStore = useUserStore();
const router = useRouter();
const { proxy } = getCurrentInstance();
const permissionStore = usePermissionStore();
const dialogShow = ref(false);
const qrCodeUrl = ref('');
const loginLoading = ref(false);
const loginForm = ref({
  username: '',
  password: '',
  rememberMe: false,
  code: '',
  uuid: '',
  otp: '',
});
const loginRules = {
  username: [{ required: true, trigger: 'blur', message: '请输入您的账号' }],
  code: [{ required: true, trigger: 'blur', message: '请输入验证码' }],
  password: [
    {
      min: 8,
      max: 20,
      message: '8-20位大小写字母+数字+特殊符号',
      required: true,
      trigger: 'blur',
      validator: validPassword,
    },
  ],
};
function validPassword(rule, value, callback) {
  // 密码校验 至少8位大小写英文字母+数字+特殊符号
  let reg = /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[^\w\s]).{8,20}$/;
  if (!reg.test(value)) {
    callback(new Error('密码8-20位大小写英文字母+数字+特殊符号'));
  } else {
    callback();
  }
}

const codeUrl = ref('');
// 验证码开关
const captchaEnabled = ref(true);

// 登录
function handleLogin() {
  proxy.$refs.loginRef.validate(valid => {
    if (valid) {
      loginLoading.value = true;
      // 勾选了需要记住密码设置在 cookie 中设置记住用户名和密码
      if (loginForm.value.rememberMe) {
        Cookies.set('usernameXG', loginForm.value.username, { expires: 30 });
        Cookies.set('passwordXG', encrypt(loginForm.value.password), {
          expires: 30,
        });
        Cookies.set('rememberMeXG', loginForm.value.rememberMe, {
          expires: 30,
        });
      } else {
        // 否则移除
        Cookies.remove('usernameXG');
        Cookies.remove('passwordXG');
        Cookies.remove('rememberMeXG');
      }
      // 调用action的登录方法
      let params = { ...loginForm.value };
      params.password = EncryptAES(params.password);

      if (params.username == 'admin') {
        // 非国密登录
        userStore
          .login(params)
          .then(res => {
            console.log(res);
            // 登录成功之后都加载对应路由
            permissionStore.generateRoutes();
            router.push({ path: '/index' });
            loginLoading.value = false;
          })
          .catch(err => {
            console.log(err);
            getCode();
            loginLoading.value = false;
          });
      } else {
        // 国密登录
        axios.post('/auth/loginByGuomi', params).then(res => {
          let datas = res.data;
          if (datas.code == 200) {
            setToken(datas.data.access_token);
            setTimeout(() => {
              // 登录成功之后都加载对应路由
              permissionStore.generateRoutes();
              router.push({ path: '/index' });
              loginLoading.value = false;
            });
          } else if (datas.code == 14140) {
            //未注册国密验证
            proxy.$modal.msgError(datas.msg);
            loginLoading.value = false;
            getCode(); //刷新二维码
            guomiCode(); // 国密注册获取二维码
            setTimeout(() => {
              dialogShow.value = true;
            }, 2000);
          } else if (datas.code == 14141) {
            //请输入手机令牌
            proxy.$modal.msgError(datas.msg);
            loginLoading.value = false;
            getCode(); //刷新二维码
            toCreateCode(datas.data); // 生成二维码
          } else if (datas.code == 14142) {
            //手机令牌不正确
            proxy.$modal.msgError(datas.msg);
            loginLoading.value = false;
            getCode(); //刷新二维码
            toCreateCode(datas.data); // 生成二维码
          } else {
            loginLoading.value = false;
            getCode(); //刷新二维码
          }
        });
      }
    }
  });
}

// 国密注册获取二维码
async function guomiCode(data) {
  let res = await guomiRegister({ username: loginForm.value.username });
  if (res.code == 200) {
    toCreateCode(res.data); // 生成二维码
  }
}
// 生成二维码
function toCreateCode(data) {
  qrcode.toDataURL(data, (err, url) => {
    if (err) {
      console.error(err);
    } else {
      qrCodeUrl.value = url;
    }
  });
}

// 获取验证码
function getCode() {
  getCodeImg().then(res => {
    captchaEnabled.value = res.captchaEnabled === undefined ? true : res.captchaEnabled;
    if (captchaEnabled.value) {
      codeUrl.value = 'data:image/gif;base64,' + res.img;
      loginForm.value.uuid = res.uuid;
    }
  });
}

function getCookie() {
  const username = Cookies.get('usernameXG');
  const password = Cookies.get('passwordXG');
  const rememberMe = Cookies.get('rememberMeXG');
  loginForm.value = {
    username: username === undefined ? loginForm.value.username : username,
    password: password === undefined ? loginForm.value.password : decrypt(password),
    rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
  };
}

onMounted(() => {
  Cookies.remove('xiaogan-Token'); //清除token
  localStorage.removeItem('routerPartXG');
  localStorage.removeItem('fromDoorXG');
  localStorage.removeItem('routerPartXG');
  getCode();
  getCookie();
});
</script>

<style lang="scss">
.guomiRegisterDia {
  display: flex;
  flex-direction: column;
  align-items: center;
  .title {
    background: linear-gradient(180deg, #015b9c 0%, #01466f 100%);
    font-size: 16px;
    padding: 15px;
    border-radius: 8px;
    margin-bottom: 20px;
    color: #fff;
    line-height: 30px;
    text-align: left;
  }
  img {
    width: 300px;
    height: 300px;
    margin-bottom: 30px;
    border: 1px solid #015b9c;
  }
}
.loginPage {
  .formCenter {
    width: 460px;
    padding: 20px;
    background: #fff;
    border-radius: 8px;
    box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.3);
    .logo {
      text-align: center;
      color: #0584ba;
      font-size: 24px;
      font-weight: 400;
      margin: 30px auto;
    }
    .loginForm {
      width: 80%;
      margin-left: 10%;
      .appNoneReg {
        color: red;
        cursor: pointer;
      }
      .el-form-item {
        margin-bottom: 30px;
        position: relative;
        .el-input {
          width: 100%;
          height: 40px;
          border-color: #8d8d8d !important;

          .el-input__wrapper {
            background: #fff !important;
            box-shadow: none;
            .el-input__inner {
              font-size: 18px;
              color: #8d8d8d !important;
            }
            svg path {
              fill: #0584ba !important;
            }
          }
          .el-input__icon {
            width: 30px;
            height: 30px;
            font-size: 22px;
          }
          input::placeholder {
            font-size: 16px;
          }
        }
        .el-form-item__error {
          left: 5px;
          top: 45px;
          font-size: 15px;
        }
        .loginBtn {
          width: 100%;
          height: 48px;
          font-size: 24px;
          font-family: PangMenZhengDao;
          font-weight: 400;
          border: none;
          background: #0584ba;
        }
      }
      .el-checkbox {
        margin: 0px 0px 15px 5px;
        .el-checkbox__label {
          color: #8d8d8d;
        }
      }

      .login-code {
        height: 40px;
        img {
          width: 120px;
          height: 40px;
          cursor: pointer;
        }
      }
    }
  }
}
</style>