This is the 28th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

[thousands of words long, stay up late to update, original is not easy, a lot of support, thank you]

preface

Hello, everyone. So far, our questionnaire survey has realized the basic functions of configuring the questionnaire, filling in the questionnaire, saving the questionnaire, submitting the questionnaire, submitting records and presenting the results. In fact, some of the related functions of the questionnaire survey have basically been realized. However, in order to make our questionnaire more perfect and more like a system, and to further learn and consolidate vue3.0 related knowledge, we continue to expand the questionnaire. Today, we will rearrange our questionnaire and add the login function.

redesign

  • The new HomePage. Vue

Before this, our questionnaire system did not pay attention to the layout. After opening it, the questionnaire filling page is displayed directly, and then the page is switched through the two hyperlinks at the top, which looks neither beautiful nor professional. Today, we will re-layout our system:

  • Add a homepage.vue component and layout it up and down and left and right, that is: first, a big box is divided into up and down parts, and then the following part is divided into left and right parts. We name them respectively: Main box, header box header-box, left box menu-box and right box Content-box
  • Add the title information of the questionnaire system and user information after login in the header-box (to be added later)
  • Introduce the El-Menu menu component from the ElementUI library into the menu-Box and display the previous two hyperlinks as menus on the left side of the page
  • Add a router-view to the menu-box to display the questionnaire content (questionnaire filling, questionnaire details, submission records, etc.)

The general layout of the page is shown below:

The following is the layout code of homepage.vue. You can make up the CSS style by yourself, or you can comment and get the complete code. The style part is not posted here. In addition, for the usage of el-menu, you can refer to the official website of Ele. me:

<template>
	<div class="main-box">
		<div class="header-box">
			<div class="header-title">
				<span>YANNIS survey management system</span>
				<div class="user">
					<div>
						<! -- Reserved: used to display user information after login -->
					</div>
					<div>
						<! -- Reserve button: the user can log out after logging in -->
					</div>
				</div>				
			</div>
		</div>
		<div class="menu-box">
			<el-menu active-text-color="#ffd04b" background-color="#4a5e71" class="el-menu-vertical-demo" text-color="#fff" router default-active="/" style="height:100%">
				<el-menu-item index="/">
					<el-icon><question-filled /></el-icon>
					<span>The questionnaire survey</span>					
				</el-menu-item>
				<el-menu-item index="/list">
					<el-icon><list /></el-icon>
					<span>Submit the record</span>					
				</el-menu-item>
			</el-menu>
		</div>
		<div class="content-box">
			<router-view />
		</div>
	</div>
</template>
Copy the code
import {ElMenu, ElMenuItem, ElIcon} from 'element-plus'
import {QuestionFilled, List} from '@element-plus/icons'
export default{
	components:{ElMenu, ElMenuItem, ElIcon, ElButton,QuestionFilled, List,SwitchButton,UserFilled},
	setup(){}}Copy the code
  • Adjust the App. Vue

The layout page has been completed, the next step is to apply it to our questionnaire system, here we need to modify our entrance page app.vue:

  • Delete the original router-link and router-view
  • Use the vue’s own component in the template. The is property is specified as HomePage
  • Import the HomePage component into the JS code and register it

The revised code of app. ue is as follows:

<template>
	<component :is="'HomePage'" />
</template>
Copy the code
import HomePage from './HomePage.vue'
export default{
	components:{ HomePage }
}
Copy the code

Does the redesigned questionnaire look more like a system and more professional?

Adding the Login function

In fact, the basic function of a questionnaire has been realized here, and the general questionnaire does not require users to log in. But this series of sharing is not to do the function of sharing, but to be able to better learn and consolidate knowledge, so we will add a forced login function for this system. Here’s a brief overview of what the login function does:

  • Start by adding a login page login.vue
  • The page should contain: user name, password, user role, login button and several other elements
    • User roles are classified into common user, administrator, and anonymous user (anonymous login is allowed).
    • Ordinary users can fill in, submit and save the questionnaire
    • The administrator has the most permissions. In addition to the permissions of common users, the administrator can configure questionnaires and collect statistics about how many questionnaires are filled in
    • Anonymous users can log in without entering the user name or password, and have the same rights as common users
    • In addition, permissions and functions are not involved in this sharing for the time being, and will be supplemented later depending on the situation (the temporary permissions of the three roles are the same, with the maximum permissions).
  • After the login succeeds, a token is generated and the token, user name, and user role are saved to vuex and localStorage
  • Verify the existence of token information before users access other functions of the system (token expiration is not considered in this sharing, only the existence of token is verified).
    • If the token exists, the access is normal
    • If the token does not exist, the login page is forcibly switched to for re-login

Special note:

  • 1. User information is stored in both VUX and localStorage. Therefore, vuEX (need to be installed separately)
  • 2. Token verification is required before requesting other functions, which involves routing navigation guard
  • 3. Anonymous login is allowed. Therefore, you need to determine the role during login. If the user is an anonymous user, you do not need to force the user name and password
  • 4. This time only simulates the login function, so it does not verify whether the user really exists or whether the password is correct
  • Install vUX (skip this step if it is already installed)
  • On the command line, switch to the root directory of the project and run: NPM install vuex@next
  • Add the store directory to the project’s SRC directory and add the index.js file to that directory
  • Open index.js and import the createStore method in vuex
  • Create and export a Store object
import { createStore } from 'vuex';

export default createStore({
	state: {token: localStorage.getItem('TOKEN') : "".// Save the token information
		userInfo: localStorage.getItem('USERINFO')?JSON.parse(localStorage.getItem('USERINFO':)) {},},mutations: {setToken(state, value){
			state.token = value;
		},
		setUserInfo(state, value){ state.userInfo = value; }}});Copy the code
  • Add the login. Vue

About login.vue page design and function description in the above steps have been introduced in the analysis, here no more to say, directly on the code, the same here only give HTML and JavaScript code, you can make up the CSS style or comment message to obtain the complete code:

<div class="login-box">
	<div class="login-form">
		<div>
			<div class="label"><label>User name:</label></div>
			<el-input type="text" v-model="name" />
		</div>
		<div>
			<div class="label"><label>The secret code:</label></div>
			<el-input type="password" v-model="pwd" />
		</div>
		<div>
			<div class="label"><label>Angle of color:</label></div>
			<el-radio-group v-model="role">
				<el-radio :label="0">The average user</el-radio>
				<el-radio :label="1">The administrator</el-radio>
				<el-radio :label="2">anonymous</el-radio>
			</el-radio-group>
		</div>
		<div>
			<el-button type="primary" @click="login">The login</el-button>
		</div>
	</div>
</div>
Copy the code
import {ElInput,ElRadio, ElRadioGroup, ElButton,ElMessage} from 'element-plus'
import constants from './constants';
import {useRouter} from 'vue-router'
import {useStore} from 'vuex'
import {reactive,toRefs} from 'vue'
export default{
	components:{ElInput,ElRadio, ElRadioGroup, ElButton,ElMessage},
	setup(){
		const router = useRouter();
		const store = useStore();
		const state = reactive({name:' '.role:0.pwd:' '})
		const login = () = >{
			if(state.role ! = =2) {if(! state.name || ! state.pwd){ ElMessage({type:"error".message:"User name or password cannot be empty"
					})
					return; }}localStorage.setItem("USERINFO".JSON.stringify({name:state.name || 'YANNIS'.role:state.role}));
			store.commit("setUserInfo", {name:state.name || 'YANNIS'.role:state.role})
			
			// Simulate to generate a token message
			let token = "djsdakfjlksdfjlsdf.sdkljfsdjfoiwendcwoeifkjlsdjfokesdjhndlk.dkjvkneoidknfiejfdkjdkljdjkl"
			localStorage.setItem("TOKEN", token);
			store.commit("setToken", token)
			router.push('/') // Adjust the home page after successful login
		}
		
		return {
			...toRefs(state),
			login
		}
	}
}
Copy the code
  • Configure the route for login.vue and add the route navigation guard

In order to verify the token validity before each request, we need to intercept the token in the route navigation guard

  • Add navigational guard router before exporting route objects. BeforeEach
  • The saved token information is obtained in localStorage
  • If the token is valid (or the login page is what the user is going to visit), the user is directly directed to the page (the login page is not blocked).
  • If the token is invalid and the login page is not accessed, lanQ interception is performed and the login page is forcibly redirected
// router/index.js
const routes = [
	/ /... omit
	{
		path:'/login'.name:'Login'.component:() = >import(/*webpackChunkName: "Login" */ '.. /login.vue')}]/ /... omit

router.beforeEach((to,from,next) = >{
		const token = localStorage.getItem("TOKEN")
		if(token || to.name === 'Login'){
			next();
		}else{
			next('/login')}})export default router;
Copy the code

App.vue gets a makeover again

Now that the login function has been implemented, we can’t wait to open the login page to try out our new feature. Alas, the login page does not open as a single page in the entire browser. Instead, it is embedded in a Content-box inside the HomePage. This is because: “We added router-view to the Content-box, and all the pages that are routed through the router-view will be displayed in the Content-box.” This is obviously not reasonable. In order for the login page to be displayed as a single page in the entire browser, We also need to rework app.vue:

  • Define a calculation property page in the setup text of app.vue
  • Import the current route information and determine whether the login page or another page is accessed based on the current route name
    • If it is a login page, assign the calculation property page to the component login corresponding to the login page
    • If it is a non-login page, the calculation property page is assigned to the corresponding component HomePage of the layout page
  • Modify the is attribute of Componen component in the template to calculate the attribute page

Before modification

<template>
	<component :is="page" />
</template>
Copy the code
	import HomePage from './HomePage.vue'
	import login from './login.vue'
	import {useRoute} from 'vue-router'
	import {computed} from 'vue';
	export default{
		components:{HomePage,login},
		setup(){
			let route = useRoute();
			const page = computed(() = >{
				return route.name === "Login" ? "login" : "HomePage";
			});
			return {
				page
			}
		}
	}
Copy the code

Then we went back to the login page and found that it already looked like what we wanted

Homepage.vue has been revamped again

After a user logs in, the user information is displayed on the right side of the top, and a logout button is added for the user to log out or switch the login operation

  • After a user logs in successfully, the user information is displayed in the upper right corner of the system
  • After a user clicks the Logout button, the user information and token information in localStorage are deleted and the login page is displayed again
<div class="user">
	<div>
		<! -- Reserved: used to display user information after login -->
		<el-icon size="25"><user-filled /></el-icon>
		<span>{{$store.state.userInfo.name}}</span>
	</div>
	<div>
		<! -- Reserve button: the user can log out after logging in -->
		<el-button type="warning" size="mini" circle :icon="SwitchButton" @click="logout"></el-button>
	</div>
</div>	
Copy the code
import {ElMenu, ElMenuItem, ElIcon, ElButton} from 'element-plus'
import {QuestionFilled, List,SwitchButton,UserFilled} from '@element-plus/icons'
import constants from './constants';
import {useRouter} from 'vue-router'
export default{
	components:{ElMenu, ElMenuItem, ElIcon, ElButton,QuestionFilled, List,SwitchButton,UserFilled},
	setup(){
		const router = useRouter();
		const logout = () = >{
			localStorage.removeItem(constants.Token);
			localStorage.removeItem(constants.UserInfo);
			router.push('/'); }}}Copy the code

The real user name is saved in the commit record

Before, we directly wrote a fake user name when saving the submission record. Now with the user login function, we should save the information of the real user who logged in:

  • Modify home. vue from vuex to useStore method and get the vuex object store
  • Change the submit method to get the user name in store and save it
// Home.vue
/ /... omit
import {useStore} from "vuex"
/ /... omit
const submit = () = >{
/ /... omit
	const record = {
		user: store.state.userInfo.name || "Yannis".time: new Date().toLocaleString(),
		question: JSON.stringify(result),
	}
/ /... omit
}
Copy the code

conclusion

In this sharing, we have rearranged the questionnaire system and added login and logout functions. The new knowledge points involved in this sharing are vuEX and routing navigation guard. In addition, the content of this sharing is scattered, there are many modules involved in modification, and all CSS styles involved are not given. If you need source partners can comment message access.

This time to share here, like small partners welcome to like comments and attention oh!