vue authority management request module encapsulation

1. Write a unified url configuration file

import { baseUrl } from './global'

export default {
  method: 'get',
  // Base url prefix
  baseUrl: baseUrl,
  // Request header information
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'Access-Control-Allow-Origin':'*',
  },
  // parameter
  data: {},
  // Set timeout
  timeout: 10000,
  // Carry credentials
  withCredentials: false,
  // Return data type
  responseType: 'json',
  //Cross domain
  changeOrigin:true
}

2. In the case of front-end and back-end separation, the url path of the back-end of the file is often modified during project test deployment, so we need to write a url configuration file of the request back-end, which is only needed to be modified each time

/**
 * Global constant, method encapsulation module
 * Mount to Vue properties via prototype
 * Call through this.Global
 */

// Background management system server address
export const baseUrl = 'http://localhost:9001'
// System data backup restore server address
export const backupBaseUrl = 'http://localhost:9001'

export default {
    baseUrl,
    backupBaseUrl
}

3. Encapsulate the axios module, which can be called uniformly. Use promise to instantiate first. Promise is actually a constructor, which has static methods such as resolve, reject and race. Its prototype has then and catch methods, so as long as it is an instance of promise, it can share and call the methods above Promise.prototype (then,catch), and add error information to rej Ect, successfully added to resolve

import axios from 'axios';
import config from './config';
import Cookies from "js-cookie";
import router from '@/router'

export default function $axios(options) {
  return new Promise((resolve, reject) => {
    const instance = axios.create({
      baseURL: config.baseUrl,
      headers: config.headers,
      timeout: config.timeout,
      changeOrigin: config.changeOrigin,
      withCredentials: config.withCredentials
    })

    // request interceptor
    instance.interceptors.request.use(
      config => {
        let token = Cookies.get('token')
        // 1. At the beginning of the request, you can start the full screen loading animation in combination with vuex
        // console.log(store.state.loading)
        // console.log('prepare to send request... ')
        // 2. Take the token
        if (token) {
          config.headers.token = token
        } else {
          // Redirect to login page
          router.push('/login')
        }
        // 3. Serialize the parameters according to the request method, and whether to serialize according to the back-end requirements
        if (config.method === 'post') {
          // if (config.data.__proto__ === FormData.prototype
          //   || config.url.endsWith('path')
          //   || config.url.endsWith('mark')
          //   || config.url.endsWith('patchs')
          // ) {

          // } else {
            // config.data = qs.stringify(config.data)
          // }
        }

        return config
      },

      error => {
        // On request error
        console.log('request:', error)
        // 1. Judge request timeout
        if (error.code === 'ECONNABORTED' && error.message.indexOf('timeout') !== -1) {
          console.log('timeout request timeout')
          // return service.request(originalRequest); / / repeat the request again
        }
        // 2. Need to redirect to error page
        const errorInfo = error.response
        console.log(errorInfo)
        if (errorInfo) {
          error = errorInfo.data  // When you catch on the other side of the page, you can get the detailed error information. Look at the project.reject at the bottom
          const errorStatus = errorInfo.status; // 404 403 500 ...
          router.push({
            path: `/error`
          })
        }
        return Promise.reject(error) // You can get the error information you want to return at the call side
      }
    )

    // response interceptor
    instance.interceptors.response.use(
      response => {
        let data;
        // When IE9, response.data is undefined, so you need to use response.request.responsetext (string after stringify)
        if (response.data == undefined) {
          data = JSON.parse(response.request.responseText)
        } else {
          data = response.data
        }

        // Do different processing according to the returned code value
        switch (data.rc) {
          case 1:
            console.log(data.desc)
            break;
          case 0:
            store.commit('changeState')
            // console.log('login succeeded ')
          default:
        }
        // If the code is not returned correctly and the user has logged in, an error will be thrown
        // const err = new Error(data.desc)
        // err.data = data
        // err.response = response
        // throw err

        return data
      },
      err => {
        if (err && err.response) {
          switch (err.response.status) {
            case 400:
              err.message = 'Request error'
              break
            case 401:
              err.message = 'Unauthorized, please log in'
              break
            case 403:
              err.message = 'access denied'
              break
            case 404:
              err.message = `Error requesting address: ${err.response.config.url}`
              break
            case 408:
              err.message = 'request timeout'
              break
            case 500:
              err.message = 'Server internal error'
              break
            case 501:
              err.message = 'Service not implemented'
              break
            case 502:
              err.message = 'Bad Gateway'
              break
            case 503:
              err.message = 'Service not available'
              break
            case 504:
              err.message = 'gateway timeout'
              break
            case 505:
              err.message = 'HTTP Version not supported'
              break
            default:
          }
        }
        console.error(err)
        return Promise.reject(err) // Returns the error information returned by the interface
      }
    )

    // Request processing
    instance(options).then(res => {
      resolve(res)
      return false
    }).catch(error => {
      reject(error)
    })
  })
}

4. After encapsulation, we only need to call at the time of each interface. Take login interface as an example

import axios from "@/http/axios";
import qs from 'qs';
let login = {};
login.subInfo = function (parms) {
  return axios({
    url: '/login',
    method: 'post',
    data:qs.stringify(parms)
  })
}
login.validateCode = function () {
  return axios({
    url: '/kaptcha/render',
    method: "get",
  })

}
export default login;

5. With the increase of interfaces, we need to write a file to call the interface uniformly

import login from '@/Api/rbac/login.js'
import user from '@/Api/rbac/user.js'
import role from '@/Api/rbac/role.js'
import menu from '@/Api/rbac/menu.js'
import dict from '@/Api/rbac/dict.js'
import dept from '@/Api/rbac/dept.js'
import log from '@/Api/rbac/log.js'

let api = {
  login,
  user,
  role,
  menu,
  dict,
  dept,
  log
}
export default api;

5. Then we mount all the structures on the $api object of the Vue prototype

// Import all interfaces

import api from "../api/Api";
const install = Vue => {
    if (install.installed)
        return;

    install.installed = true;

    Object.defineProperties(Vue.prototype, {
        // Note that this is mounted on the $api object of the Vue prototype
        $api: {
            get() {
                return api
            }
        }
    })
}

export default install

6. Finally, add it in main.js, and then you can reference it globally

import api from './http'
import global from '@/http/global'
Vue.use(api)
Vue.prototype.global = global

7. Write a login page. I write js, scss and vue separately

<template>
  <div class="login-container">
    <el-form :model="loginInfo" :rules="myrule"
             status-icon
             ref="loginInfo"
             label-position="left"
             label-width="0px"
             class="demo-ruleForm login-page">
      <h3 class="title">facing the sea with spring flowers blossoming</h3>
      <el-form-item prop="username">
        <el-input prefix-icon="el-icon-user-solid" v-model="loginInfo.username"
                  auto-complete="off"/>
      </el-form-item>
      <el-form-item prop="password">
        <el-input prefix-icon="el-icon-lock" type="password" v-model="loginInfo.password"
                  auto-complete="off"/>
      </el-form-item>
      <el-form-item prop="code" class="code">
        <el-input prefix-icon="el-icon-lock" v-model="loginInfo.verifyCode" placeholder="Verification Code"></el-input>
        <img :src="loginInfo.src" @click="clickCapatch"/>
      </el-form-item>
      <el-form-item>
        <el-checkbox v-model="checked" class="rememberme" style="float:left;">Remember password</el-checkbox>
        <a class="login-form-forgot" @click="froget" style="float:right;" href="javascript:;">Forget password </a>
      </el-form-item>
      <el-form-item style="width:100%;">
        <el-button type="primary" style="width:100%;" @click="loginafter" :loading="loading">Sign in</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script src="@/views/login/login.js"></script>
<style scoped src="@/views/login/login.scss"></style>

 

import url from "@/http/global";
import Cookies from "js-cookie";
export default {
  name: 'login',
  data() {
    return {
      loading: false,
      loginInfo: {
        username: 'root',
        password: '123456',
        verifyCode: "",
        src: url.baseUrl + "/kaptcha/render"
      },
      myrule: {
        username: [{required: true, message: 'please enter your account', trigger: 'blur'}],
        password: [{required: true, message: 'enter your password', trigger: 'blur'}]
      },
      checked: false
    }
  },
  methods: {
    clickCapatch: function () {
      this.loginInfo.src = url.baseUrl + '/kaptcha/render?time='+new Date();
    },
    froget() {

    },
    loginafter() {
      let that = this
      let params = {
        username: that.loginInfo.username,
        password: that.loginInfo.password,
        validateCodeText: that.loginInfo.verifyCode,
        captcha: Cookies.get("captcha")
      }
      this.$api.login.subInfo(params).then(res => {
        try {
          var dateStatus = res.status
          if (203 == dateStatus) {
              Cookies.set('token', res.jwtToken)
            this.$router.push({path: '/home',});
          } else {
            this.$router.push({path: '/error',});
          }
        } catch (e) {
          this.$router.push({path: '/error',});
        }
      })
    }
  }
};

 

.login-container {
  width: 100%;
  height: 100%;
  background : #f0f2f5 url('../../assets/background.jpg') no-repeat;
}
.login-page {
  -webkit-border-radius: 5px;
  border-radius: 5px;
  margin: 180px auto;
  width: 350px;
  padding: 35px 35px 15px;
  background: #fff;
  border: 1px solid #eaeaea;
  box-shadow: 0 0 25px #cac6c6;
}

.rememberme .el-checkbox {
  margin: 0px 0px 15px;
  text-align: left;
}

.code {
  position: relative;
  margin-top: 20px;
  display: block;
  width: 60%;
}

img {
  position: absolute;
  height: 35px;
  margin-left: 16px;
}

Finally, add the login page to the route

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'login',
      component: () => import('@/views/login/login.vue'),
    },
    {
      path: '/home',
      name: 'home',
      component: () => import('@/views/home/home.vue'),
    },
    {
      path: '/error',
      name: 'error',
      component: () => import('@/views/error.vue'),
    }
  ]
})

Start view page effect

Published 34 original articles, won praise 7, visited 4119
Private letter follow

Tags: Vue axios JSON Spring

Posted on Mon, 13 Jan 2020 22:00:28 -0800 by naboth_abaho