vue front-end and back-end separate back-end management system (rights management, login), front-end scaffolding. Docking backend is a backend interface based on SpringSecurity

Posted by empnorton on Sat, 05 Mar 2022 18:26:09 +0100

Article Directory

Foreword (very important)

Management System Backend (java) Refer to: https://blog.csdn.net/grd_java/article/details/121925792

Source code for this project, CodeCloud: https://gitee.com/yin_zhipeng/vue-backstage-scaffolding.git

Background management system is generally used by internal personnel, so the interface requirements are not high, generally using templates for development. And the foreground system is for tourists to use, to highlight personality, so generally develop by yourself, do not use templates

  1. If you want to write from start to finish, you can refer to my foreground system. Every detail will be covered (you can write your own template after reading): @TODO and write later
  2. Here is the background management system, we use the template "PanJiaChen's Template Simple Edition"
  1. Simple version: https://github.com/PanJiaChen/vue-admin-template
  2. Enhanced version: https://github.com/PanJiaChen/vue-element-admin
  1. If GitHub can't get in, you can download it here (code cloud): https://gitee.com/panjiachen/vue-admin-template.git

Once the download is complete, we use it as a project, execute npm install --save to download the dependencies, launch the project through npm run dev, and finally view the project in the browser



Project Final Results Show @TODO

1. Summary of concepts and technologies (key points must be understood)

This summary summarizes the front-end knowledge used in the project, which will not be repeated later

  1. You need to be familiar with the code at least, so you don't know what it is used for (many people use it now, but don't know why, how do you optimize and tune, and make mistakes?)
  2. If there's something you won't or haven't seen here (which I can't understand after reading my introduction), you can refer to the official documents (that means you haven't learned Vue at all, just Baidu Vue's official website).

1. vue

The way components communicate (the six most basic)

  1. props: For scenarios where parent-child components communicate, there is one easy point to confuse, as follows:
  1. If a parent component uses props to pass data to a child component, it passes a function, which is essentially a child component passing data to the parent component (because the parent component's function is called).
  2. If it is not a function that is passed in, then it is the real parent component that passes data to the child component (the child component uses the incoming data).
  3. You can specify either the type of parent component transport, {type:Array}, the default value, {type:Array,default:[]}, or nothing, ['todos']
  1. Custom Events: $on, $emit for child components to pass data to parent components
  2. Global Event Bus $bus: for any scenario, Vue.prototype. $bus = this;
  3. pubsub-js Publishing and Subscription: Suitable for any scenario, but Vue is not used much and is often used by React frameworks
  4. Vuex: suitable for any scene, used a lot
  5. solt slot: Used for parent-child component communication for structures (labels), commonly used are default slots, named slots, and scope slots

2. vue-admin-template template file parsing

File directory parsing (Note: All folders and files below will work the same for you, not necessarily in this template file)

build 
	--index.js webpack configuration file[We hardly need to change]
mock
	--mock Data Folder[Simulate some false data, mock.js Realization],We already have a backend and an interface, and we don't need it at all
node_modules
	--Project Dependent Modules
p ublic
	--Deposit ico Static resources such as icons, static pages, webpack When packaging, this folder will not be compiled and will not be packaged in its original state dist Folder
src --Where we write code
	--api Folder: Asynchronous request related code
	--assets Folder: Static resources, generally shared, but here static resources, webpack Packaging is compilable
	--components Folder: Global component (non-routing component)
	--icons Folder: svg Vector Graph
	--layout Folder: Place some components and mix-ins mixin
	--router Folder: Routing-related
	--store Folder: vuex Dependent
	--style Folder: Style-dependent
	--utils Folder: Tool class, where request.js yes axios Secondary packaging, more common
	--views Folder: Routing component (not global component)
App.vue
	--Root Component
main.js
	--Entry File
permission.js
	--Navigation guard, mainly controls login and other related affairs
settings
	--For project configurations (for the display layer), such as our browser Tags title What to show, whether the header is fixed, navigation bar logo Is it displayed

--There are configuration files left
.editorconfig
	--Programming style configuration, such as indentation with two spaces
-- Three important profiles are available through webpack Exposed Functions process Obtain
.env.development
	-- Configuration file for development environment
.env.production
	-- Configuration file for online environment
.env.staging
	-- Configuration file for test environment

-- Three configuration files that are important but not important
.eslintignore
	-- eslint Detected Ignore Files, for which it will ignore, and we don't need them at all eslint Testing
.eslintrc.js
	-- eslint configuration file
.gitignore
	-- Only related to author, upload git Ignore files for

-- Uncommonly used profiles
.travis.yml
	-- Some languages, development version configuration files
babel.config.js
	-- babel A configuration file, often used to configure on-demand loading, such as element ui Load on demand
jest.config.js
	-- Configuration file for test framework
LICENSE
	-- Copyright Statement Files
-- Key Profiles
jsconfig.json
	-- To configure src Alias File
package.json
	-- Configure project information, run parameters, required dependencies
postcss.config.js
	-- css Configuration files, compatibility issues with different browsers, can be resolved here
vue.config.js
	-- Can act as webpack.config.js,Acting as a proxy, we often use this file

router folder index.js parsing

  1. First, the routing module is mounted to the Vue, then all the routing configurations are encapsulated in the constant constantRoutes, then the callback function creates the route, mounts the constant constantRoutes, places the function into the constant createRouter, and then replaces the function constant createRouter() with a simple name router. Finally, resetRouter() which exposes routers externally and resets routers externally
  2. By doing so, we can get route-related information directly through the $router operation

jsconfig.json file configuration src alias @parse

Three environment profiles, which can be obtained through the webpack exposed function process, note that the content in the configuration file should be VUE_APP_***** Beginning (just like the initial letters of java class names should be capitalized, so everyone should follow them together)

  1. Let's look at the configuration contents of the configuration file for the development environment and test if it is correctly obtained
  2. Main. Output process and process in JS file. Env, view results

console.log(process)
console.log(process.env)

Auth in utils. JS file details

  1. Functions for permissions are encapsulated here

store Folder Details

  1. index.js file, mainly to control the overall situation of Vuex, mounted to Vue
  2. getters.js file, encapsulating getters operations, where lambda expressions (arrow functions) are used uniformly, using the app and user content in the modules configured above, such as state.app. *****
//lambda is a representation of a parameter that we pass is a, followed by execution logic
a =>  return a;

  1. user.js, which provides login state s, setter s (action s and mutations), and exposes them. Another app.js, settings.js file and user.js is almost

3. Asynchronous correlation, front-end and back-end interaction

1. When PanJiaChen developed this template, there was no async function (the syntax of ES6), so using traditional Promise to handle asynchronism, we will change it to use async function later. For Promise and async, refer to the article: https://blog.csdn.net/grd_java/article/details/105384601

2. request.js file

4. Navigation Guard

Unknown reference to official documents https://router.vuejs.org/zh/guide/advanced/navigation-guards.html

permission.js file parsing

  1. This file mainly controls the business of route jump, which, like a navigation, can be understood as the interceptor of a route
  2. The main function of this file is to intercept a route jump, determine whether the user has a token, if so, whether the jump route is/login, and if so, not allowed, from the orientation to the'/'home page. If it is not a login path, try to get user information, cannot get it, try to retrieve it again, retrieve it failed, delete token, and let the user enter the login page to log in again

5. Routing Resolution

Remember, all routes are looking for < router-view>, all child routes are looking for < router-view> in the parent routing component

When the whole route enters the first page, it is the Layout component, which is divided into three parts, sidebar navigation bar, navbar top menu bar, app-main internal secondary route, where we actually write the page

  1. Routing analysis, when we access'/'it loads the Layout component and then redirects to / dashboard, which is the second-level route, showing the first page (shown in the < router-view > label), as well as the others
  2. Layout component analysis, a total of 3 sub-components
  3. scrollbar
  4. navbar
  5. AppMain, visible < router-view > label In this component, subroutes will be rendered here

2. Single sign-on implementation

The login page is provided directly from the template and we'll make some modifications to its style to let you know how to customize it

  1. Change the background picture, or use the @ symbol with a ~prefix
  1. Add a back to the assets file. Jpg picture
  2. Modify css Style


1. Backend interface and response result analysis

  1. Authentication code: Ask captcha to return a picture
  2. Login, Post request, transfer username, password, code three parameters, all correct, login success, return tokenHead and token, the final token format is, tokenHead + space + token, that is, Bearer eyJh..., success status code 20000, failure status code 20001

  3. Currently logged in user information, need to carry token, note that token format, and header name are authorization

2. Resolve cross-domain and request headers. Almost all projects need to be configured. Check it out.

1. First, we know that there is a VUE_in the environment configuration file APP_ BASE_ API is something that we use to specify the request path, and we can specify it. Remember to restart the project when you are finished (we are the development environment, so modify the.env.development file)

2. We then modify the webpack configuration file vue.config.js, configure cross-domain proxy, primary location, don't write wrong location, again, remember to restart the project after configuring

    //Configure proxy across domains
    proxy: {
      [process.env.VUE_APP_BASE_API]: {
        target: `http://localhost:8001`, //Modify background interface address
        // changeOrigin: true,
        pathRewrite: {
          ['^'+process.env.VUE_APP_BASE_API]: ''
        }
      }
    },

3. A token request header is something you can configure directly into the request interceptor, request.js, note that the key of the token request header must be authorization (because this is what our backend specifies, not this, the backend cannot parse properly)

// request interceptor
service.interceptors.request.use(
  config => {
    // do something before request is sent
    if (store.getters.token) {
      // let each request carry token
      // ['X-Token'] is a custom headers key
      // please modify it according to the actual situation
      config.headers['authorization'] = getToken()
    }
    return config
  },
  error => {
    // do something with request error
    console.log(error) // for debug
    return Promise.reject(error)
  }
)

3. Verification code display

Backend just returns a picture to us, we can use window. url. CreateObject url (response) to get a url address for the picture

window.URL.createObjectURL is used to create a new object URL that can represent a specified File or Blob object

  1. Response type must be blob or file (responseType:'blob'or responseType:'file')

The effect is as follows

1. First, the Authentication Code function of our backend does not have a response code, and the template we use is at request.js encapsulates request interceptor and response interceptor, fatally, response interceptor directly intercepts all responses whose response code is not 20000

  1. The advantage of this is that if all requests go wrong (the response code is not 20000), the error logic will be unified, but this is also a disadvantage. Because we want different feedback for different errors, not one uniform
  2. So we want to enrich its functionality (one if) for responses that don't require a code status code, if there is a responder, it means the response is successful, otherwise it means the response failed.

2. Encapsulate api requests, be careful to set the response type to'blob'(responseType:'blob')

  1. api/user.js Add Authentication Code Interface
export function captcha() {
  return request({
    url: 'captcha',
    method: 'get',
    responseType:'blob'
  })
}

3. login page, login/index.js file introduces api, then shows verification code

  1. Write the function getImgCode through window. url. CreateObject url (response) encapsulates the picture as a url

    //Get Authentication Code Asynchronously
    async getImgCode () {
      await captcha().then(response => {
        this.codesrc = window.URL.createObjectURL(response)
      })
    },
  1. Add components and styles, specify function callbacks (click events) to enable clicking pictures and regenerating validation codes

//html tags
      <el-form-item prop="code" class="code">
        <span class="svg-container">
<!--          <svg-icon icon-class="el-icon-s-flag" />-->
          <i class="el-icon-edit"></i>
        </span>

        <el-input
          class="code-input"
          ref="code"
          type="text"
          v-model="loginForm.code"
          placeholder="Verification Code"
          name="code"
          tabindex="2"
          auto-complete="on"
          @keyup.enter.native="handleLogin"
        />

      </el-form-item>
      <img :src="codesrc" class="code-img" @click="getImgCode">
//sass style
  .code{
    width: 70%;
    float: left;
  }
  .code-img{
    float: right;
    width: 29.6%;
    //height: 100%;
  }

4. Single sign-on, logout, based on back-end API implementation

The effect is as follows

  1. After logging in, view token

  2. Log out and view token

1. api interface

api folder user.js file, modify login, getInfo and logout three interfaces

2. Routing component writes login function logic

We found that all login logic for this template is view/login/index. Modify handleLogin method in Vue file

    handleLogin() {
      this.$refs.loginForm.validate(valid => {
        if (valid) {//After form validation occurs
          this.loading = true//Logon button available
          //Call action listening, user. login below JS
          this.$store.dispatch('user/login', this.loginForm).then(() => {
            this.$router.push({ path: this.redirect || '/' })//Successfully jumped route, triggering permission.js Navigation Guard
            this.loading = false//Prevent use of login button during asynchronous process
          }).catch(() => {
            this.loading = false//Prevent login buttons from being used during asynchronization
            this.getImgCode()//Logon Failure, Refresh Authentication Code
          })
        } else {
          console.log('error submit!!')
          this.getImgCode()//Refresh Authentication Code
          return false
        }
      })
    }

3. Modify store (vuex) asynchronous logic

All operations are in store/user. In js, we need to modify login and getInfo and logout


  // user login
  //Processing login business
  async login({ commit },userInfo) {
    //Deconstruct user name and password
    const { username,password,code} = userInfo;
    //login under asynchronous call/api/user file
    let result = await login({username: username.trim(),password:password,code:code});
    if (result.code==20000){
      //We specify token as a tokenHead + "" + token string
      const token = result.data.tokenHead+' '+result.data.token;
      //Set to state
      commit("SET_TOKEN",token);
      //Through auth.js file function, set to cookie
      setToken(token)
    }else{
      //Logon Failure
      return Promise.reject(new Error(result.message));
    }
  },

  // get user info
  async getInfo({ commit, state }) {
    //login under asynchronous call/api/user file
    let result = await getInfo(state.token);
    if(result.code === 20000){
      const { loginInfo } = result.data
      if (!loginInfo) {
        return reject('Authentication failed, please log in again.');
      }
      const {username} = loginInfo;
      commit('SET_NAME',username);
      commit('SET_AVATAR','https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif')
    }else{
      //Logon Failure
      return Promise.reject(new Error(result.message));
    }
  },
  // user logout
  async logout({ commit, state }) {
    let result = await logout(state.token);
    if(result.code === 20000){
      removeToken() // must remove  token  first
      resetRouter()
      commit('RESET_STATE')
    }else{
      //Log out failed
      return Promise.reject(new Error(result.message));
    }
  },

5. Process Summary

  1. this.$store.dispatch('user/login', this.loginForm), calls login
  2. This. $ Router. Push ({path: this.redirect ||'/'})// successfully jumps the route, triggering permission.js Navigation Guard
  3. Navigation guard, call getInfo according to token to get user information, can't get, delete token, overload route to login page

3. Implementation of Background Management System

For space reasons, I put it in another article: @TODO is not finished yet

Topics: Javascript Front-end Vue.js html