534 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Vue
		
	
	
	
			
		
		
	
	
			534 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Vue
		
	
	
	
<template>
 | 
						|
  <div class="container">
 | 
						|
    <div class="login">
 | 
						|
      <div class="login-form" style="width: 450px;">
 | 
						|
        <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" >
 | 
						|
          <h3 class="title">智慧食堂系统</h3>
 | 
						|
          <template v-if="loginMethod === 'password'">
 | 
						|
            <el-form-item prop="username">
 | 
						|
              <el-input
 | 
						|
                v-model="loginForm.username"
 | 
						|
                type="text"
 | 
						|
                auto-complete="off"
 | 
						|
                :placeholder="`用户名${config.loginConfig.phonePassword ? '/手机号' : ''}${config.loginConfig.emailPassword ? '/邮箱' : ''}`"
 | 
						|
              >
 | 
						|
                <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon"/>
 | 
						|
              </el-input>
 | 
						|
            </el-form-item>
 | 
						|
            <el-form-item prop="password">
 | 
						|
              <el-input
 | 
						|
                v-model="loginForm.password"
 | 
						|
                type="password"
 | 
						|
                auto-complete="off"
 | 
						|
                placeholder="密码"
 | 
						|
                @keyup.enter.native="handleLogin"
 | 
						|
              >
 | 
						|
                <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon"/>
 | 
						|
              </el-input>
 | 
						|
            </el-form-item>
 | 
						|
            <el-form-item prop="code" v-if="captchaEnabled">
 | 
						|
              <el-input
 | 
						|
                v-model="loginForm.code"
 | 
						|
                auto-complete="off"
 | 
						|
                placeholder="验证码"
 | 
						|
                style="width: 63%"
 | 
						|
                @keyup.enter.native="handleLogin"
 | 
						|
              >
 | 
						|
                <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon"/>
 | 
						|
              </el-input>
 | 
						|
              <div class="login-code">
 | 
						|
                <img :src="codeUrl" @click="getCode" class="login-code-img"/>
 | 
						|
              </div>
 | 
						|
            </el-form-item>
 | 
						|
            <el-form-item v-show="isAdmin" prop="verificationCode">
 | 
						|
              <el-input v-model="loginForm.verificationCode" placeholder="请输入验证码">
 | 
						|
                <template slot="append">
 | 
						|
                  <el-button
 | 
						|
                    type="primary"
 | 
						|
                    @click="sendAdminCode"
 | 
						|
                    :disabled="isSendingCode || captchaEnabled?!loginForm.code:false"
 | 
						|
                    class="send-code-button"
 | 
						|
                  >
 | 
						|
                    {{ countdown === 0 ? '获取验证码' : `${countdown}s` }}
 | 
						|
                  </el-button>
 | 
						|
                </template>
 | 
						|
                <svg-icon slot="prefix" icon-class="message" class="el-input__icon input-icon"/>
 | 
						|
              </el-input>
 | 
						|
            </el-form-item>
 | 
						|
          </template>
 | 
						|
          <template v-else>
 | 
						|
            <el-form-item prop="mobile">
 | 
						|
              <el-input
 | 
						|
                v-model="loginForm.mobile"
 | 
						|
                type="text"
 | 
						|
                auto-complete="off"
 | 
						|
                :placeholder="`${config.loginConfig.phoneCode ? '手机号' : '/'}${config.loginConfig.emailCode ? '邮箱' : ''}`"
 | 
						|
              >
 | 
						|
                <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon"/>
 | 
						|
              </el-input>
 | 
						|
            </el-form-item>
 | 
						|
            <el-form-item prop="code" v-if="captchaEnabled">
 | 
						|
              <el-input
 | 
						|
                v-model="loginForm.code"
 | 
						|
                auto-complete="off"
 | 
						|
                placeholder="验证码"
 | 
						|
                style="width: 63%"
 | 
						|
                @keyup.enter.native="handleLogin"
 | 
						|
              >
 | 
						|
                <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon"/>
 | 
						|
              </el-input>
 | 
						|
              <div class="login-code">
 | 
						|
                <img :src="codeUrl" @click="getCode" class="login-code-img"/>
 | 
						|
              </div>
 | 
						|
            </el-form-item>
 | 
						|
            <el-form-item prop="verificationCode">
 | 
						|
              <el-input v-model="loginForm.verificationCode" placeholder="请输入验证码">
 | 
						|
                <template slot="append">
 | 
						|
                  <el-button
 | 
						|
                    type="primary"
 | 
						|
                    @click="sendCode"
 | 
						|
                    :disabled="isSendingCode || captchaEnabled?!loginForm.code:false"
 | 
						|
                    class="send-code-button"
 | 
						|
                  >
 | 
						|
                    {{ countdown === 0 ? '获取验证码' : `${countdown}s` }}
 | 
						|
                  </el-button>
 | 
						|
                </template>
 | 
						|
                <svg-icon slot="prefix" icon-class="message" class="el-input__icon input-icon"/>
 | 
						|
              </el-input>
 | 
						|
            </el-form-item>
 | 
						|
          </template>
 | 
						|
          <div class="login-form-center">
 | 
						|
            <el-link v-if="config.loginConfig.emailCode ||config.loginConfig.phoneCode " @click="toggleLoginMethod">
 | 
						|
              {{ loginMethod === 'password' ? '短信登录' : '密码登录' }}
 | 
						|
            </el-link>
 | 
						|
            <router-link v-if="config.registersConfig.emailRegisters || config.registersConfig.phoneRegisters" to="/register">
 | 
						|
              <el-link>注册账号</el-link>
 | 
						|
            </router-link>
 | 
						|
            <el-checkbox v-model="loginForm.rememberMe">记住密码</el-checkbox>
 | 
						|
          </div>
 | 
						|
          <el-form-item style="width: 100%;">
 | 
						|
            <el-button v-if="!isAdmin"
 | 
						|
                       :loading="loading"
 | 
						|
                       size="medium"
 | 
						|
                       type="primary"
 | 
						|
                       style="width: 100%;"
 | 
						|
                       @click="loginMethod === 'password' ?IsAdmin():handleLogin()"
 | 
						|
            >
 | 
						|
              <span v-if="!loading">登 录</span>
 | 
						|
              <span v-else>登 录 中...</span>
 | 
						|
            </el-button>
 | 
						|
            <el-button v-if="isAdmin"
 | 
						|
                       :loading="loading"
 | 
						|
                       size="medium"
 | 
						|
                       type="primary"
 | 
						|
                       style="width: 100%;"
 | 
						|
                       @click="handleLogin()"
 | 
						|
            >
 | 
						|
              <span v-if="!loading">登 录</span>
 | 
						|
              <span v-else>登 录 中...</span>
 | 
						|
            </el-button>
 | 
						|
          </el-form-item>
 | 
						|
          <!-- <el-form-item>
 | 
						|
            <div class="login-divider">第三方登录</div>
 | 
						|
            <div class="login-icons">
 | 
						|
              <div class="login-icon">
 | 
						|
                <img :src="dingding" alt="Weibo">
 | 
						|
              </div>
 | 
						|
              <div class="login-icon">
 | 
						|
                <img :src="wx" alt="WeChat">
 | 
						|
              </div>
 | 
						|
              <div class="login-icon">
 | 
						|
                <img :src="qq" alt="QQ">
 | 
						|
              </div>
 | 
						|
            </div>
 | 
						|
          </el-form-item> -->
 | 
						|
        </el-form>
 | 
						|
      </div>
 | 
						|
    </div>
 | 
						|
  </div>
 | 
						|
</template>
 | 
						|
 | 
						|
<script>
 | 
						|
import { getCodeImg } from '@/api/login'
 | 
						|
import Cookies from 'js-cookie'
 | 
						|
import { decrypt, encrypt } from '@/utils/jsencrypt'
 | 
						|
import dingding from '@/assets/images/dingding.svg'
 | 
						|
import wx from '@/assets/images/wx.svg'
 | 
						|
import qq from '@/assets/images/QQ.svg'
 | 
						|
 | 
						|
export default {
 | 
						|
  name: 'Login',
 | 
						|
  data() {
 | 
						|
    return {
 | 
						|
      dingding: dingding,
 | 
						|
      wx: wx,
 | 
						|
      qq: qq,
 | 
						|
      codeUrl: '',
 | 
						|
      isAdmin: false,
 | 
						|
      loginForm: {
 | 
						|
        username: '',
 | 
						|
        password: '',
 | 
						|
        rememberMe: false,
 | 
						|
        code: '',
 | 
						|
        mobile: '',
 | 
						|
        verificationCode: '',
 | 
						|
        uuid: '',
 | 
						|
        loginType: '',
 | 
						|
        phoneUuid: '',
 | 
						|
        mobileCodeType: 'LOGIN'
 | 
						|
      },
 | 
						|
      passwordLoginRules: {
 | 
						|
        username: [{ required: true, trigger: 'blur', message: '请输入您的账号' }],
 | 
						|
        password: [{ required: true, trigger: 'blur', message: '请输入您的密码' }],
 | 
						|
        code: [{ required: true, trigger: 'change', message: '请输入验证码' }]
 | 
						|
      },
 | 
						|
      mobileLoginRules: {
 | 
						|
        mobile: [{ required: true, trigger: 'blur', message: '请输入您的手机号' }],
 | 
						|
        verificationCode: [{ required: true, trigger: 'blur', message: '请输入验证码' }]
 | 
						|
      },
 | 
						|
      loading: false,
 | 
						|
      captchaEnabled: true,
 | 
						|
      redirect: undefined,
 | 
						|
      isSendingCode: false,
 | 
						|
      countdown: 0,
 | 
						|
      loginMethod: 'password', // 'password' or 'mobile'
 | 
						|
      supportsPhoneLogin: false,
 | 
						|
      supportsEmailLogin: false
 | 
						|
    }
 | 
						|
  },
 | 
						|
  computed: {
 | 
						|
    config() {
 | 
						|
      return JSON.parse(localStorage.getItem('systemConfig')) || {loginConfig:{
 | 
						|
        phonePassword: true,
 | 
						|
          emailPassword: true,
 | 
						|
          phoneCode: false,
 | 
						|
          emailCode: false
 | 
						|
      },registersConfig: {
 | 
						|
          phoneRegisters: true,
 | 
						|
          emailRegisters: true
 | 
						|
        }}; // 获取 JSON 对象
 | 
						|
    },
 | 
						|
    loginRules() {
 | 
						|
      return this.loginMethod === 'password' ? this.passwordLoginRules : this.mobileLoginRules
 | 
						|
    }
 | 
						|
  },
 | 
						|
  watch: {
 | 
						|
    $route: {
 | 
						|
      handler(route) {
 | 
						|
        this.redirect = route.query && route.query.redirect
 | 
						|
      },
 | 
						|
      immediate: true
 | 
						|
    }
 | 
						|
  },
 | 
						|
  created() {
 | 
						|
    this.getCode()
 | 
						|
    this.getCookie()
 | 
						|
  },
 | 
						|
  methods: {
 | 
						|
    getCode() {
 | 
						|
      getCodeImg().then(res => {
 | 
						|
        this.captchaEnabled = res.captchaEnabled !== undefined ? res.captchaEnabled : true
 | 
						|
        if (this.captchaEnabled) {
 | 
						|
          this.codeUrl = 'data:image/gif;base64,' + res.img
 | 
						|
          this.loginForm.uuid = res.uuid
 | 
						|
        }
 | 
						|
      })
 | 
						|
    },
 | 
						|
    getCookie() {
 | 
						|
      const username = Cookies.get('username')
 | 
						|
      const password = Cookies.get('password')
 | 
						|
      const rememberMe = Cookies.get('rememberMe')
 | 
						|
      this.loginForm.username = username || ''
 | 
						|
      this.loginForm.password = password ? decrypt(password) : ''
 | 
						|
      this.loginForm.rememberMe = rememberMe === 'true'
 | 
						|
    },
 | 
						|
    handleLogin() {
 | 
						|
      this.$refs.loginForm.validate(valid => {
 | 
						|
        if (valid) {
 | 
						|
          this.loading = true
 | 
						|
          if (this.loginForm.rememberMe) {
 | 
						|
            Cookies.set('username', this.loginForm.username, { expires: 30 })
 | 
						|
            Cookies.set('password', encrypt(this.loginForm.password), { expires: 30 })
 | 
						|
            Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 })
 | 
						|
          } else {
 | 
						|
            Cookies.remove('username')
 | 
						|
            Cookies.remove('password')
 | 
						|
            Cookies.remove('rememberMe')
 | 
						|
          }
 | 
						|
          this.loginForm.loginMethod = this.loginMethod
 | 
						|
          this.$store.dispatch('Login', this.loginForm)
 | 
						|
            .then(res => {
 | 
						|
              this.loading = false
 | 
						|
              // console.log(res)
 | 
						|
              if (res.code===200){
 | 
						|
                if (res.isLogin){
 | 
						|
                  this.$modal.confirm('账号已在其他地方登录是否继续登录!!!!').then(function() {
 | 
						|
                    return this.$router.push({ path: this.redirect || '/canteen/index' });
 | 
						|
                  }).then(() => {
 | 
						|
                    this.loading = false
 | 
						|
                  }).catch(() => {
 | 
						|
                    this.loading = false
 | 
						|
                  })
 | 
						|
                }else {
 | 
						|
                  this.$router.push({ path: this.redirect || '/canteen/index' });
 | 
						|
                }
 | 
						|
              }
 | 
						|
            })
 | 
						|
            .catch(() => {
 | 
						|
              this.loading = false
 | 
						|
              if (this.captchaEnabled) this.getCode()
 | 
						|
            })
 | 
						|
        }
 | 
						|
      })
 | 
						|
    },
 | 
						|
    IsAdmin() {
 | 
						|
      this.loginForm.loginMethod = this.loginMethod
 | 
						|
      this.$store.dispatch('IsAdmin', this.loginForm).then(res => {
 | 
						|
        if (res.data) {
 | 
						|
          this.isAdmin = res.data
 | 
						|
          this.$message.success('检测到您是超级管理账号,需进行手机检验')
 | 
						|
        } else {
 | 
						|
          this.handleLogin()
 | 
						|
        }
 | 
						|
      })
 | 
						|
    },
 | 
						|
    isLogin() {
 | 
						|
      this.$refs.loginForm.validate(valid => {
 | 
						|
        if (valid) {
 | 
						|
          this.loading = true
 | 
						|
          let that = this
 | 
						|
          this.loginForm.loginMethod = this.loginMethod
 | 
						|
          this.$store.dispatch('IsLogin', this.loginForm)
 | 
						|
            .then(res => {
 | 
						|
              if (res.data) {
 | 
						|
                this.$modal.confirm('账号已在其他地方登录是否继续登录!!!!').then(function() {
 | 
						|
                  return that.handleLogin()
 | 
						|
                }).then(() => {
 | 
						|
                  this.loading = false
 | 
						|
                }).catch(() => {
 | 
						|
                  this.loading = false
 | 
						|
                })
 | 
						|
              } else {
 | 
						|
                that.handleLogin()
 | 
						|
              }
 | 
						|
            })
 | 
						|
            .catch(() => {
 | 
						|
              this.loading = false
 | 
						|
              if (this.captchaEnabled) this.getCode()
 | 
						|
            })
 | 
						|
        }
 | 
						|
      })
 | 
						|
    },
 | 
						|
    sendAdminCode() {
 | 
						|
      this.loginForm.mobile = this.loginForm.username
 | 
						|
      this.$store.dispatch('GetPhoneCode', this.loginForm)
 | 
						|
        .then(res => {
 | 
						|
          if (res.code === 200) {
 | 
						|
            this.loginForm.phoneUuid = res.data
 | 
						|
            this.$message.success('验证码发送成功')
 | 
						|
            this.isSendingCode = true
 | 
						|
            this.countdown = 60
 | 
						|
            const timer = setInterval(() => {
 | 
						|
              this.countdown -= 1
 | 
						|
              if (this.countdown <= 0) {
 | 
						|
                clearInterval(timer)
 | 
						|
                this.isSendingCode = false
 | 
						|
              }
 | 
						|
            }, 1000)
 | 
						|
          }
 | 
						|
        })
 | 
						|
        .catch(() => {
 | 
						|
          this.loading = false
 | 
						|
          // 如果启用了验证码,则重新获取验证码
 | 
						|
          if (this.captchaEnabled) {
 | 
						|
            this.getCode()
 | 
						|
          }
 | 
						|
          // 其他失败处理逻辑
 | 
						|
          this.isSendingCode = false
 | 
						|
          this.countdown = 0
 | 
						|
        })
 | 
						|
    },
 | 
						|
    sendCode() {
 | 
						|
      if (this.captchaEnabled ? !this.loginForm.code : false) {
 | 
						|
        this.$message.error('请先填写验证码')
 | 
						|
        return
 | 
						|
      }
 | 
						|
      if (!this.loginForm.mobile) {
 | 
						|
        this.$message.error('请先填写'+this.config.loginConfig.phoneCode ? '手机号' : '/' + this.config.loginConfig.emailCode ? '邮箱' : '')
 | 
						|
        return
 | 
						|
      }
 | 
						|
      this.$store.dispatch('GetPhoneCode', this.loginForm)
 | 
						|
        .then(() => {
 | 
						|
          this.isSendingCode = true
 | 
						|
          this.countdown = 60
 | 
						|
          const timer = setInterval(() => {
 | 
						|
            this.countdown -= 1
 | 
						|
            if (this.countdown <= 0) {
 | 
						|
              clearInterval(timer)
 | 
						|
              this.isSendingCode = false
 | 
						|
            }
 | 
						|
          }, 1000)
 | 
						|
        })
 | 
						|
        .catch(() => {
 | 
						|
          this.loading = false
 | 
						|
          // 如果启用了验证码,则重新获取验证码
 | 
						|
          if (this.captchaEnabled) {
 | 
						|
            this.getCode()
 | 
						|
          }
 | 
						|
          // 其他失败处理逻辑
 | 
						|
          this.isSendingCode = false
 | 
						|
          this.countdown = 0
 | 
						|
        })
 | 
						|
    },
 | 
						|
    toggleLoginMethod() {
 | 
						|
      this.loginMethod = this.loginMethod === 'password' ? 'mobile' : 'password'
 | 
						|
      this.loginForm.username = ''
 | 
						|
      this.loginForm.password = ''
 | 
						|
      this.loginForm.code = ''
 | 
						|
      this.loginForm.verificationCode = ''
 | 
						|
      this.loginForm.loginMethod = ''
 | 
						|
      this.isAdmin = false
 | 
						|
      this.getCode()
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
</script>
 | 
						|
 | 
						|
<style lang="scss">
 | 
						|
.container {
 | 
						|
  display: flex;
 | 
						|
  justify-content: flex-end;
 | 
						|
  align-items: center;
 | 
						|
  height: 100%;
 | 
						|
  width: 100%;
 | 
						|
  background-image: url("../assets/images/login-bg.png"); 
 | 
						|
  background-repeat: no-repeat;
 | 
						|
  background-size: 100% 100%; /* 确保背景图覆盖整个容器 */
 | 
						|
  background-position: center center; /* 居中显示背景图 */ 
 | 
						|
}
 | 
						|
 | 
						|
.login {
 | 
						|
  width: 50%;
 | 
						|
  display: flex;
 | 
						|
  justify-content: center;
 | 
						|
  align-items: center;
 | 
						|
  height: 100%;
 | 
						|
}
 | 
						|
 | 
						|
.title {
 | 
						|
  margin: 0 auto 30px;
 | 
						|
  text-align: center;
 | 
						|
  color: #707070;
 | 
						|
}
 | 
						|
 | 
						|
.login-form {
 | 
						|
  border-radius: 6px;
 | 
						|
  background: #ffffff;
 | 
						|
  width: 400px;
 | 
						|
  padding: 25px;
 | 
						|
 | 
						|
  .el-input {
 | 
						|
    height: 38px;
 | 
						|
 | 
						|
    input {
 | 
						|
      height: 38px;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  .input-icon {
 | 
						|
    height: 39px;
 | 
						|
    width: 14px;
 | 
						|
    margin-left: 2px;
 | 
						|
  }
 | 
						|
 | 
						|
  .login-form-center {
 | 
						|
    display: flex;
 | 
						|
    justify-content: space-between;
 | 
						|
    align-items: flex-start;
 | 
						|
    padding: 1%;
 | 
						|
    margin-bottom: 5%;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
.login-tip {
 | 
						|
  font-size: 13px;
 | 
						|
  text-align: center;
 | 
						|
  color: #bfbfbf;
 | 
						|
}
 | 
						|
 | 
						|
.login-code {
 | 
						|
  width: 33%;
 | 
						|
  float: right;
 | 
						|
 | 
						|
  img {
 | 
						|
    cursor: pointer;
 | 
						|
    vertical-align: middle;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
.el-login-footer {
 | 
						|
  height: 40px;
 | 
						|
  line-height: 40px;
 | 
						|
  position: fixed;
 | 
						|
  bottom: 0;
 | 
						|
  width: 100%;
 | 
						|
  text-align: center;
 | 
						|
  color: #fff;
 | 
						|
  font-family: Arial;
 | 
						|
  font-size: 12px;
 | 
						|
  letter-spacing: 1px;
 | 
						|
}
 | 
						|
 | 
						|
.login-code-img {
 | 
						|
  height: 38px;
 | 
						|
}
 | 
						|
 | 
						|
.login-container {
 | 
						|
  text-align: center;
 | 
						|
  margin-top: 50px;
 | 
						|
}
 | 
						|
 | 
						|
.login-divider {
 | 
						|
  display: flex;
 | 
						|
  align-items: center;
 | 
						|
  text-align: center;
 | 
						|
  margin: 20px 0;
 | 
						|
}
 | 
						|
 | 
						|
.login-divider::before,
 | 
						|
.login-divider::after {
 | 
						|
  content: '';
 | 
						|
  flex: 1;
 | 
						|
  border-bottom: 1px solid #ccc;
 | 
						|
}
 | 
						|
 | 
						|
.login-divider:not(:empty)::before {
 | 
						|
  margin-right: .25em;
 | 
						|
}
 | 
						|
 | 
						|
.login-divider:not(:empty)::after {
 | 
						|
  margin-left: .25em;
 | 
						|
}
 | 
						|
 | 
						|
.login-icons {
 | 
						|
  display: flex;
 | 
						|
  justify-content: center;
 | 
						|
  gap: 20px;
 | 
						|
}
 | 
						|
 | 
						|
.login-icon {
 | 
						|
  width: 50px;
 | 
						|
  height: 50px;
 | 
						|
  border-radius: 50%;
 | 
						|
  display: flex;
 | 
						|
  align-items: center;
 | 
						|
  justify-content: center;
 | 
						|
  cursor: pointer;
 | 
						|
}
 | 
						|
 | 
						|
.login-icon img {
 | 
						|
  width: 50px;
 | 
						|
  height: 50px;
 | 
						|
}
 | 
						|
</style>
 |