MrShi
2 天以前 eb82684152ffb0acddf67da92e4533a0190eb258
admin/src/views/login.vue
@@ -1,36 +1,96 @@
<template>
  <div class="wrap">
    <div class="introduce">
      <h2>豆米跳跳</h2>
      <h3></h3>
    </div>
    <div class="login">
      <h1>系统登录&nbsp;/&nbsp;LOGIN IN</h1>
      <div class="info-input">
        <el-input v-model="username" placeholder="请输入用户名" prefix-icon="el-icon-user-solid" maxlength="50" v-trim/>
        <el-input v-model="password" placeholder="请输入密码" type="password" prefix-icon="eva-icon-password" maxlength="30" show-password/>
        <div class="captcha-input">
          <el-input v-model="captcha.value" placeholder="图片验证码" prefix-icon="eva-icon-shield" maxlength="4" @keypress.enter.native="login"/>
          <img v-if="!captcha.loading" :src="captcha.uri" @click="refreshCaptcha">
          <span v-else><i class="el-icon-loading"></i></span>
    <img src="@/assets/images/bg@2x.png" class="main_bg" alt="">
    <div class="login_wrap">
      <div class="login_img">
        <div class="h2">芜湖烟草智慧安消安全防范系统</div>
        <div class="h3">智慧物流园区安消一体化系统</div>
      </div>
      <div class="form_wrap">
        <div class="tabs">
          <div class="tab" @click="tabClick('0')" :class="{ active: activeTab == '0' }">
            <div class="name">帐号登录</div>
            <div class="icon"></div>
          </div>
          <div class="tab" @click="tabClick('1')" :class="{ active: activeTab == '1' }">
            <div class="name">手机登录</div>
            <div class="icon"></div>
          </div>
        </div>
        <template v-if="activeTab == '0'">
          <div class="df_ac">
            <div class="label">帐号</div>
            <div class="line">
              <el-input v-model="username" placeholder="请输入帐号" maxlength="50" v-trim />
            </div>
          </div>
          <div class="df_ac">
            <div class="label">密码</div>
            <div class="line">
              <el-input v-model="password" placeholder="请输入密码" type="password" maxlength="30" show-password />
            </div>
          </div>
          <div class="df_ac">
            <div class="label">验证码</div>
            <div class="line">
              <el-input v-model="captcha.value" placeholder="请输入验证码" maxlength="4" @keypress.enter.native="login" />
              <img v-if="!captcha.loading" class="code_image" :src="captcha.uri" @click="refreshCaptcha">
              <span v-else><i class="el-icon-loading"></i></span>
            </div>
          </div>
        </template>
        <template v-if="activeTab == '1'">
          <div class="df_ac">
            <div class="label">手机号</div>
            <div class="line">
              <el-input v-model="phone" placeholder="请输入手机号" type="text" maxlength="16" />
            </div>
          </div>
          <div class="df_ac">
            <div class="label">验证码</div>
            <div class="line">
              <el-input v-model="smsCode" placeholder="请输入验证码" maxlength="6" @keypress.enter.native="login" />
              <span v-if="downTime == 0" class="code_get" @click="getCode">获取验证码</span>
              <span v-else class="code_get downtime">{{ downTime }}</span>
            </div>
          </div>
        </template>
        <el-button :loading="loading" type="primary" class="login_btn" @click.native.prevent="login">立即登录</el-button>
        <div class="btn_wrap">
          <el-checkbox v-model="isRemPsd">
            <span style="font-size: 13px; font-weight: 400" class="placeholder9">{{ activeTab == 0 ? '记住密码' : '记住手机号'
              }}</span>
          </el-checkbox>
        </div>
        <div class="google">
          <img src="@/assets/images/ic_google@2x.png" class="img" alt="">
          <span class="placeholder6">本系统推荐使用GOOGLE浏览器</span>
        </div>
      </div>
      <el-button :loading="loading" @click="login">登&nbsp;&nbsp;录</el-button>
    </div>
  </div>
</template>
<script>
import { mapMutations } from 'vuex'
import { getCaptcha, loginByPassword } from '@/api/system/common'
import { getCaptcha, loginByPassword, sendSmsPost, loginByPhone } from '@/api/system/common'
import Cookies from "js-cookie"
import { Message } from 'element-ui'
export default {
  name: 'Login',
  data () {
  data() {
    return {
      loading: false,
      isRemPsd: false,
      username: '',
      password: '',
      phone: '',
      downTime: 0,
      smsCode: '',
      activeTab: '0',
      // 验证码
      captcha: {
        loading: false,
@@ -40,36 +100,97 @@
      }
    }
  },
  mounted() {
    this.username = localStorage.getItem('username') || ''
    this.password = localStorage.getItem('password') || ''
    this.phone = localStorage.getItem('phone') || ''
    const isRemPsd = localStorage.getItem('isRemPsd') || false
    this.isRemPsd = JSON.parse(isRemPsd)
    this.refreshCaptcha()
  },
  methods: {
    ...mapMutations(['setUserInfo']),
    // 登录
    login () {
    login() {
      if (this.loading) {
        return
      }
      if (!this.__check()) {
        return
      }
      this.loading = true
      loginByPassword({
        username: this.username.trim(),
        password: this.password,
        code: this.captcha.value.trim(),
        uuid: this.captcha.uuid
      })
        .then(() => {
          window.location.href = process.env.VUE_APP_CONTEXT_PATH
      if (this.activeTab == 0) {
        if (!this.__check()) {
          return
        }
        this.loading = true
        loginByPassword({
          username: this.username.trim(),
          password: this.password,
          code: this.captcha.value.trim(),
          uuid: this.captcha.uuid
        })
        .catch(e => {
          .then((res) => {
            // window.location.href = process.env.VUE_APP_CONTEXT_PATH
            if (this.isRemPsd) {
              localStorage.setItem('username', this.username.trim())
              localStorage.setItem('password', this.password.trim())
              localStorage.setItem('isRemPsd', this.isRemPsd)
            } else {
              localStorage.removeItem('username')
              localStorage.removeItem('password')
              localStorage.removeItem('isRemPsd')
            }
            Cookies.set('dm_user_token', res)
            this.$router.push('index')
          })
          .catch(e => {
            this.refreshCaptcha()
          })
          .finally(() => {
            this.loading = false
          })
      } else {
        const { smsCode, phone } = this
        if (!phone || phone.length != 11) {
          return Message.error('请输入正确的手机号')
        }
        if (!smsCode) {
          return Message.error('请输入验证码')
        }
        this.loading = true
        loginByPhone({ phone, code: smsCode }).then(res => {
          if (this.isRemPsd) {
            localStorage.setItem('phone', this.username.trim())
          }
          Cookies.set('dm_user_token', res)
          this.$router.push('index')
        }).catch(e => {
          this.refreshCaptcha()
          this.$tip.apiFailed(e)
        })
        .finally(() => {
        }).finally(() => {
          this.loading = false
        })
      }
    },
    getCode() {
      console.log('getCode')
      const { phone } = this
      if (!phone || phone.length != 11) {
        return Message.error('请输入正确的手机号')
      }
      sendSmsPost({ phone, type: 0 }).then(res => {
        Message.success('短信发送成功')
        this.downTime = 60
        let timer = setInterval(() => {
          if (this.downTime == 0) {
            return clearInterval(timer)
          }
          this.downTime--
        }, 1000)
      })
    },
    tabClick(val) {
      this.activeTab = val
    },
    // 刷新验证码
    refreshCaptcha () {
    refreshCaptcha() {
      this.captcha.loading = true
      getCaptcha()
        .then(data => {
@@ -86,7 +207,7 @@
        })
    },
    // 登录前验证
    __check () {
    __check() {
      if (this.username.trim() === '') {
        this.$tip.error('请输入用户名')
        return false
@@ -102,47 +223,252 @@
      return true
    }
  },
  created () {
    this.refreshCaptcha()
  }
}
</script>
<style scoped lang="scss">
@import "@/assets/style/variables.scss";
div {
  box-sizing: border-box;
}
$input-gap: 30px;
.wrap {
  display: flex;
  width: 100%;
  height: 100vh;
  background-image: url("../assets/images/login.jpg");
  background-repeat: no-repeat;
  background-size: auto 180%;
  background-clip: content-box;
  background-position: center;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  // 左边介绍
  .introduce {
    padding-left: 10%;
  .main_bg {
    position: absolute;
    width: 100%;
    height: 100%;
    left: 0;
    top: 0;
    z-index: -1;
  }
  .login_wrap {
    width: 1000px;
    height: 600px;
    box-sizing: border-box;
    color: #fff;
    background: rgba(0, 0, 0, 0.4);
    background: #ffffff;
    box-shadow: 0px 20px 60px 0px rgba(0, 0, 0, 0.11);
    display: flex;
    flex-direction: column;
    justify-content: center;
    h2 {
      font-size:34px;
      font-style: italic;
      font-weight: 900;
      margin-top: 50px;
    .login_img {
      width: 500px;
      height: 600px;
      background: url("../assets/images/login_img@2x.png");
      background-size: 100% 100%;
      padding-left: 40px;
      padding-top: 60px;
      .h2 {
        color: $primary-color;
        background-color: #fff;
        height: 24px;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 4px;
        width: 208px;
        display: flex;
        margin-bottom: 12px;
      }
      .h3 {
        font-size: 28px;
        font-weight: 700;
        color: #fff;
        margin-bottom: 26px;
      }
      .text {
        font-size: 18px;
        color: #fff;
      }
    }
    h3 {
      font-size: 49px;
      font-weight: 300;
      margin: 25px 0;
    .form_wrap {
      flex: 1;
      height: 100%;
      background-color: #fff;
      box-sizing: border-box;
      /* padding: 50px 80px 20px; */
      padding: 50px 80px 20px;
      position: relative;
      .tabs {
        display: flex;
        justify-content: space-evenly;
        font-size: 20px;
        color: #666666;
        margin-bottom: 30px;
        .tab {
          display: flex;
          flex-direction: column;
          justify-content: center;
          align-items: center;
          cursor: pointer;
          .icon {
            width: 36px;
            height: 4px;
            background: #fff;
            border-radius: 2px;
            margin-top: 8px;
          }
        }
        .active {
          font-weight: 500;
          font-size: 24px;
          color: #222222;
          .icon {
            background: #207FF7;
          }
        }
      }
      .df_ac {
        flex-direction: column;
        align-items: flex-start;
      }
      .title {
        font-size: 24px;
        margin-top: 70px;
        margin-bottom: 48px;
        text-align: center;
      }
      .label {
        color: #222222;
        margin-bottom: 18px;
        font-size: 14px;
        margin-right: 12px;
        width: 42px;
      }
      &.ey {
        .label {
          width: 135px;
        }
      }
      .line {
        margin-bottom: 17px;
        display: flex;
        width: 100%;
        align-items: center;
        position: relative;
        .el-input {
          height: 40px;
          flex: 1;
          // font-size: 14px;
          ::v-deep .el-input__inner {
            height: 40px !important;
          }
        }
        .code_image {
          width: 100px;
          margin-left: 10px;
        }
        .code_get {
          position: absolute;
          top: 10px;
          right: 10px;
          font-size: 14px;
          width: 72px;
          z-index: 11;
          margin-left: 10px;
          cursor: pointer;
          color: $primary-color;
          text-align: right;
        }
        .downtime {
          color: #999999;
        }
      }
      .forget {
        justify-content: space-between;
        width: 100%;
        .text {
          cursor: pointer;
        }
      }
      .login_btn {
        width: 100%;
        height: 40px;
        background: $primary-color;
        box-shadow: 0px 2px 8px 0px rgba(67, 94, 190, 0.15);
        border-radius: 2px;
        margin: 0 auto;
        font-weight: 500;
        font-size: 16px;
      }
      .google {
        position: absolute;
        left: 50%;
        transform: translate(-50%, 0);
        bottom: 20px;
        display: flex;
        align-items: center;
        justify-content: center;
        width: 100%;
        font-size: 12px;
        .img {
          margin-right: 5px;
          width: 18px;
        }
      }
      .btn_wrap {
        margin-top: 20px;
      }
      .agreement {
        text-align: center;
      }
      .google {
        position: absolute;
        left: 50%;
        transform: translate(-50%, 0);
        bottom: 20px;
        display: flex;
        align-items: center;
        justify-content: center;
        width: 100%;
        font-size: 12px;
        .img {
          margin-right: 5px;
          width: 18px;
        }
      }
    }
  }
  // 右边登录
  .login {
    height: 100%;
@@ -157,40 +483,50 @@
    flex-direction: column;
    justify-content: center;
    box-sizing: border-box;
    h1 {
      font-size: 28px;
      font-weight: 500;
    }
    .info-input {
      margin-top: $input-gap;
      margin-bottom: 60px;
      /deep/ .el-input {
        margin-top: 30px;
        .el-input__inner {
          height: 50px;
          background: #F9F9F9;
          border: 1px solid transparent;
          &:focus {
            border: 1px solid $primary-color;
          }
        }
      }
    }
    // 验证码输入
    .captcha-input {
      display: flex;
      margin-top: $input-gap;
      height: 50px;
      .el-input {
        width: 100%;
        margin-top: 0;
      }
      span, img {
      span,
      img {
        width: 45%;
        height: 100%;
        flex-shrink: 0;
        margin-left: 16px;
      }
      span {
        display: flex;
        align-items: center;
@@ -199,6 +535,7 @@
        border-radius: 8px;
      }
    }
    .el-button {
      height: 50px;
      width: 100%;