前端登陆业务逻辑

前端登陆业务逻辑

  1. 封装axios
  2. 封装接口请求
  3. 封装登录请求动作
  4. 保存服务端返回的token
  5. 登录鉴权
代码实现
  • 创建登录表单
<template>
  <div class="login-container">
    <el-form
      class="login-form"
      ref="loginFormRef"
      :model="loginForm"
      :rules="loginRules"
    >
      <div class="title-container">
        <h3 class="title">用户登陆</h3>
      </div>
      <!-- username  -->
      <el-form-item prop="username">
        <span class="svg-container">
          <svg-icon icon="user"></svg-icon>
        </span>
        <el-input
          placeholder="username"
          name="username"
          type="text"
          v-model="loginForm.username"
        ></el-input>
      </el-form-item>
      <!-- password  -->
      <el-form-item prop="password">
        <span class="svg-container">
          <svg-icon icon="password"></svg-icon>
        </span>
        <el-input
          placeholder="password"
          name="password"
          :type="passwordType"
          v-model="loginForm.password"
        ></el-input>
        <span class="show-pwd">
          <span class="svg-container" @click="onChangePwdType">
            <svg-icon
              :icon="passwordType === 'password' ? 'eye' : 'eye-open'"
            ></svg-icon>
          </span>
        </span>
      </el-form-item>
      <!-- 登陆按钮 -->
      <el-button
        type="primary"
        style="width: 100%; margin-bottom: 30px"
        :loading="loading"
        @click="handlerLogin"
      >
        登陆
      </el-button>
    </el-form>
  </div>
</template>
  • 数据源
// 数据源
const loginForm = ref({
  username: 'sysadmin@thingsboard.org',
  password: 'sysadmin'
})

  • 封装验证规则


// 外部封装规则
export const validatePassword = () => {
  return (rule, value, callback) => {
    if (value.length < 6) {
      callback(new Error('密码不能小于6位'))
    } else {
      callback()
    }
  }
}


// 验证规则
const loginRules = ref({
  username: [
    {
      required: true,
      trigger: 'blur',
      message: '用户名为必填项'
    }
  ],
  password: [
    {
      required: true,
      trigger: 'blur',
      validator: validatePassword()
    }
  ]
})

// 处理密码框文本显示
const passwordType = ref('password')
// template中绑定的方法直接声明即可
const onChangePwdType = () => {
  // 当passwordType的值为password的时候改为text
  // 使用ref声明的数据,在script中使用时需要加value来获取具体的值 Templates中使用的时候 不需要加value
  if (passwordType.value === 'password') {
    passwordType.value = 'text'
  } else {
    passwordType.value = 'password'
  }
}
  • 处理登录请求

// 处理登陆
const loading = ref(false)
const store = useStore()
const loginFormRef = ref(null)
const handlerLogin = () => {
  // 进行表单校验
  // console.log(loginFormRef.value)
  loginFormRef.value.validate((valid) => {
    if (!valid) return
    // 触发登陆动作
    loading.value = true
    store
      .dispatch('user/login', loginForm.value)
      .then(() => {
        loading.value = false
        // 进行登陆后处理
      })
      .catch((err) => {
        console.log(err)
        loading.value = false
      })
  })
}
  • 封装登录请求动作
import { login } from '@/api/sys'
// import md5 from 'md5'
import { setItem, getItem } from '@/utils/storage'
import { TOKEN, REFRESHTOKEN } from '@/constant'
import router from '@/router'

export default {
  namespaced: true,
  state: () => ({
    token: getItem(TOKEN) || ''
  }),
  mutations: {
    setToken(state, data) {
      state.token = data.token
      setItem(TOKEN, data.token)
      setItem(REFRESHTOKEN, data.refreshToken)
    }
  },
  /**
   * 登陆请求动作
   */
  actions: {
    login(context, userInfo) {
      const { username, password } = userInfo
      return new Promise((resolve, reject) => {
        login({
          username,
          password
          // password: md5(password)
        })
          .then((data) => {
            // console.log(data)
            this.commit('user/setToken', data)
            // 跳转
            router.push('/')
            resolve()
          })
          .catch((err) => {
            reject(err)
          })
      })
    }
  }
}

  • 创建响应拦截器
import axios from 'axios'
import { ElMessage } from 'element-plus'

const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API,
  timeout: 5000
})

// 响应拦截器
service.interceptors.response.use(
  // 请求成功
  (response) => {
    const data = response.data

    // 需要判断当前请求是否成功
    if (data != null) {
      // 成功返回解析后的数据
      const message1 = '-登陆成功-'
      ElMessage.success(message1)
      return data
    } else {
      // 失败(请求成功,业务失败) 消息提示
      const message1 = '-请求成功,业务失败-'
      ElMessage.error(message1)
      return Promise.reject(new Error(message1))
    }
  },
  // 请求失败
  (error) => {
    const message2 = '-请求失败-'
    ElMessage.error(message2)
    return Promise.reject(error)
  }
)

export default service

设置登录鉴权

import { createRouter, createWebHashHistory } from 'vue-router'

/**
 * 公开路由表
 */
const publicRoutes = [
  {
    path: '/login',
    component: () => import('@/views/login/index')
  },
  {
    path: '/',
    component: () => import('@/layout/index')
  }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes: publicRoutes
})

export default router

  • 前置导航守卫
import router from '@/router'
import store from '@/store'

// 白名单
const whileList = ['/login']

/**
 * 路由前置守卫
 * @param {*} to  要到那里去
 * @param {*} from  你从哪里来
 * @param {*} next  是否要去
 */
router.beforeEach((to, from, next) => {
  // 用户以登陆,不允许进入login
  // 用户未登陆,只允许进入login
  if (store.getters.token) {
    // 用户以登陆,不允许进入login
    if (to.path === '/login') {
      next('/')
    } else {
      next()
    }
  } else {
    // 用户未登陆,只允许进入login
    if (whileList.indexOf(to.path) > -1) {
      next()
    } else {
      next('/login')
    }
  }
})

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值