设置路由
E:\dongli\power-supervision-system\src\api\moudules\login.js
import request from '@/utils/request'
/**
* 登录模块
*/
/**
* 登录
* @param {*} params
*/
export const login = (params) => {
return request({
url: '/user/login',
method: 'get',
params
})
}
/**
* 退出登录
* @param {*} params
*/
export const logout = (params) => {
return request({
url: '/user/logout',
method: 'get',
params
})
}
用户登录
E:\dongli\power-supervision-system\src\api\moudules\user.js
import request from '@/utils/request'
/**
* 用户列表
* @param {*} params
*/
export const getUserList = params => {
return request({
url: '/user/getUserList',
method: 'get',
params
})
}
/**
* 用户登录
* @param {userName:'',password:''} params
*/
export const login = params=>{
return request({
url: '/login/checkLogin',
method: 'post',
params
})
}
/**
* 用户注册步骤1校验企业名称
* @param {companyName:''} params
*/
export const isRegister = params=>{
return request({
url: '/login/isRegister',
method: 'post',
params
})
}
/**
* 用户注册
* @param {companyId:'',……} params
*/
export const register = params=>{
return request({
url: '/login/register',
method: 'post',
params
})
}
/**
* 用户退出
* @param {userId:'',……} params
*/
export const logout = params=>{
return request({
url: '/login/logout',
method: 'post',
params
})
}
路由页
E:\dongli\power-supervision-system\src\router\index.js
import {createRouter, createWebHashHistory} from 'vue-router'
import Auth from '@/utils/auth'
import Layout from '../views/layout'
const whiteList = ['/login','/dashboard']
const routes = [
{
path: '/',
redirect: '/dashboard'
}, {
path: "/dashboard",
name: "dashboard",
meta: {
title: '系统首页'
},
component: () => import (
/* webpackChunkName: "dashboard" */
"../views/Dashboard.vue")
},
{
path: "/",
name: "Layout",
component: Layout,
children: [
]
}, {
path: "/login",
name: "Login",
meta: {
title: '登录'
},
component: () => import (
/* webpackChunkName: "login" */
"../views/login.vue")
}
];
const router = createRouter({
history: createWebHashHistory(),
routes
});
router.beforeEach((to, from, next) => {
document.title = `${to.meta.title} | ${window.g.title}`;
if(Auth.getToken()) {
if (to.path === '/login') {
next({ path: '/' })
} else if(to.path.indexOf("/error") >= 0){
// 防止因重定向到error页面造成beforeEach死循环
next()
} else {
//store.dispatch('GenerateRoutes').then((res) => {
next()
//})
}
} else {
// 没有token
if (whiteList.indexOf(to.path) !== -1) {
// 在免登录白名单,直接进入
next()
} else {
next(`/login`) // 否则全部重定向到登录页
}
}
});
export default router;
用户页js
E:\dongli\power-supervision-system\src\store\modules\user.js
import { login, logout } from '@/api/moudules/login'
import authToken from '@/utils/auth'
import { ElMessage } from 'element-plus'
const user = {
namespaced: true,
state: {
token: authToken.getToken(),
// 用户名
username: localStorage.getItem('username'),
userId: ''
},
mutations: {
SET_TOKEN: (state, token) => {
state.token = token
},
SET_USERNAME: (state, username) => {
state.username = username;
localStorage.setItem("username",username);
},
SET_USERID: (state, userId) => {
localStorage.setItem("userId",userId);
state.userId = userId;
}
},
actions: {
// 登录
Login({ commit }, userInfo) {
return new Promise((resolve, reject) => {
login(userInfo).then(res => {
if(res.code == 200) {
let data = res.data
commit('SET_USERNAME', data.loginName)
commit('SET_USERID', data.userId)
commit('SET_TOKEN', data.token)
authToken.setToken(data.token)
resolve(data)
}else{
ElMessage.error(res.msg)
}
}).catch(error => {
reject(error)
})
})
},
// 退出登录
LogOut({ commit }) {
return new Promise((resolve, reject) => {
logout().then(() => {
commit('SET_TOKEN', '')
authToken.removeToken()
resolve()
}).catch(error => {
reject(error)
})
})
}
}
}
export default user
设置token
E:\dongli\power-supervision-system\src\utils\auth.js
import Cookies from 'js-cookie'
const authToken = {
// 在Cookie中记录登录状态的key
tokenKey: 'token',
// 获取Token
getToken: function() {
return Cookies.get(this.tokenKey)
},
// 设置Token
setToken: function(token) {
// TODO: 设置token,并填写有效期
var maxAge = new Date(new Date().getTime() + 1800 * 1000)
Cookies.set(this.tokenKey, token, {
expires: maxAge
})
},
// 移除Token
removeToken: function(){
Cookies.remove(this.tokenKey)
}
}
export default authToken
request 请求
E:\dongli\power-supervision-system\src\utils\request.js
import axios from 'axios'
import { ElMessage } from 'element-plus'
import router from "@/router/index";
import Auth from '@/utils/auth'
let base_url;
if (process.env.NODE_ENV === 'production') {
base_url = window.g.baseURL
} else if (process.env.NODE_ENV === 'development') {
base_url = '/api/'
}
// create an axios instance
const service = axios.create({
baseURL: base_url, // api 的 base_url
withCredentials: true,
timeout: 300000 // request timeout
})
// request interceptor
service.interceptors.request.use(
config => {
if(!Auth.getToken())
{
//router.push("/login");
return config
}else{
config.headers['token'] = Auth.getToken()
return config
}
},
error => {
// Do something with request error
Promise.reject(error)
}
)
// response interceptor
service.interceptors.response.use(
response => {
let data;
// IE9时response.data是undefined,因此需要使用response.request.responseText(Stringify后的字符串)
if (response.data == undefined) {
data = JSON.parse(response.request.responseText)
} else {
if(response.config.responseType)
data = response
else{
data = response.data
if (data.code === 600) {
console.log('跳到登录页')
//清空token
Auth.removeToken()
router.push("/login");
}
}
}
return data
},
error => {
if (error && error.response) {
switch (error.response.status) {
case 400:
error.message = '数据请求错误'
break
case 401:
error.message = '未授权,请登录'
break
case 403:
error.message = '拒绝访问'
break
case 404:
error.message = '请求地址出错'
break
case 408:
error.message = '请求超时'
break
case 500:
error.message = '服务器内部错误'
break
case 501:
error.message = '服务未实现'
break
case 502:
error.message = '网关错误'
break
case 503:
error.message = '服务不可用'
break
case 504:
error.message = '网关超时'
break
case 505:
error.message = 'HTTP版本不受支持'
break
default:
}
}
ElMessage({
message: error.message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
)
export default service
初始登录页?
E:\dongli\power-supervision-system\src\views\Login-bak.vue
<template>
<div class="login-wrap">
<div class="ms-login">
<div class="ms-title">后台管理系统</div>
<el-form :model="param" :rules="rules" ref="login" label-width="0px" class="ms-content">
<el-form-item prop="username">
<el-input v-model="param.username" placeholder="username">
<template #prepend>
<el-button icon="el-icon-user"></el-button>
</template>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
type="password"
placeholder="password"
v-model="param.password"
@keyup.enter="submitForm()"
>
<template #prepend>
<el-button icon="el-icon-lock"></el-button>
</template>
</el-input>
</el-form-item>
<div class="login-btn">
<el-button type="primary" @click="submitForm()">登录</el-button>
</div>
<p class="login-tips">Tips : 用户名和密码随便填。</p>
</el-form>
</div>
</div>
</template>
<script>
export default {
data() {
return {
param: {
username: "admin",
password: "123123"
},
rules: {
username: [
{ required: true, message: "请输入用户名", trigger: "blur" }
],
password: [
{ required: true, message: "请输入密码", trigger: "blur" }
]
}
};
},
created() {
this.$store.commit("clearTags");
},
methods: {
submitForm() {
this.$refs.login.validate(valid => {
if (valid) {
this.$message.success("登录成功");
localStorage.setItem("ms_username", this.param.username);
this.$router.push("/");
} else {
this.$message.error("请输入账号和密码");
return false;
}
});
}
}
};
</script>
<style scoped>
.login-wrap {
position: relative;
width: 100%;
height: 100%;
background-image: url(../assets/img/login-bg.jpg);
background-size: 100%;
}
.ms-title {
width: 100%;
line-height: 50px;
text-align: center;
font-size: 20px;
color: #fff;
border-bottom: 1px solid #ddd;
}
.ms-login {
position: absolute;
left: 50%;
top: 50%;
width: 350px;
margin: -190px 0 0 -175px;
border-radius: 5px;
background: rgba(255, 255, 255, 0.3);
overflow: hidden;
}
.ms-content {
padding: 30px 30px;
}
.login-btn {
text-align: center;
}
.login-btn button {
width: 100%;
height: 36px;
margin-bottom: 10px;
}
.login-tips {
font-size: 12px;
line-height: 30px;
color: #fff;
}
</style>
登录页 vue
E:\dongli\power-supervision-system\src\views\login.vue
<template>
<div class="login-container">
<!-- 登录 -->
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on" label-position="left">
<div class="title-container">
<h3 class="title">{{title}}</h3>
</div>
<el-form-item prop="loginName">
<span class="iconfont icon-user"></span>
<el-input v-model="loginForm.loginName" placeholder="请输入账号" name="loginName" type="text" auto-complete="on" />
</el-form-item>
<el-form-item prop="password">
<span class="iconfont icon-password"></span>
<el-input v-model="loginForm.password" :type="passwordType" placeholder="请输入密码" name="password" auto-complete="on" @keyup.enter="handleLogin" />
<span class="show-pwd" @click="showPwd">
<i class="iconfont" :class="passwordType === 'password' ? 'icon-eye' : 'icon-eye-open'"></i>
</span>
</el-form-item>
<el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.prevent="handleLogin">
登录
</el-button>
</el-form>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'Login',
data() {
return {
title: '',
loginForm: {
loginName: 'admin',
password: '123456'
},
loginRules: {
loginName: [{
required: true,
trigger: 'blur',
'message': '请输入用户名'
}],
password: [{
required: true,
trigger: 'blur',
'message': '请输入密码'
}]
},
passwordType: 'password',
loading: false,
redirect: undefined
}
},
watch: {
$route: {
handler: function(route) {
this.redirect = route.query && route.query.redirect
},
immediate: true
}
},
computed: {
title() {
return window.g.title
}
},
methods: {
showPwd() {
if (this.passwordType === 'password') {
this.passwordType = ''
} else {
this.passwordType = 'password'
}
},
handleLogin() {
this.$refs.loginForm.validate(valid => {
if (valid) {
this.$store.dispatch("user/Login", this.loginForm).then((res) => {
this.$router.push('/');
})
.catch(() => {
this.loading = false;
});
}
else {
return false
}
})
}
}
}
</script>
<style lang="scss">
$bg: #283443;
$light_gray: #eee;
$cursor: #fff;
@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
.login-container .el-input input{
color: $cursor;
&::first-line {
color: $light_gray;
}
}
}
/* reset element-ui css */
.login-container {
.el-input {
display: inline-block;
height: 47px;
width: 85%;
input {
height: 47px;
padding: 12px 5px;
color: $light_gray;
border: 0px;
border-radius: 0px;
background: transparent;
caret-color: $cursor;
-webkit-appearance: none;
&:-webkit-autofill {
-webkit-box-shadow: 0 0 0px 1000px $bg inset !important;
-webkit-text-fill-color: $cursor !important;
}
}
}
.el-form-item {
color: #454545;
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 5px;
background: rgba(0, 0, 0, 0.1);
}
}
</style>
<style lang="scss" scoped>
// $bg: #2d3a4b;
$bg: transparent;
$dark_gray: #889aa4;
$light_gray: #eee;
.login-container {
width: 100%;
min-height: 100%;
background-color: #2d3a4b;
overflow: hidden;
.login-form {
position: relative;
width: 520px;
max-width: 100%;
padding: 160px 35px 0;
margin: 0 auto;
overflow: hidden;
}
.tips {
margin-bottom: 10px;
font-size: 14px;
color: #fff;
span {
&:first-of-type {
margin-right: 16px;
}
}
}
.iconfont {
display: inline-block;
width: 30px;
padding: 6px 5px;
color: $dark_gray;
font-size: 16px;
vertical-align: middle;
text-align: center;
}
.title-container {
position: relative;
.title {
margin: 0px auto 40px auto;
font-size: 26px;
font-weight: bold;
color: $light_gray;
text-align: center;
}
.set-language {
position: absolute;
top: 3px;
right: 0;
font-size:18px;
color: #fff;
cursor: pointer;
}
}
.show-pwd {
position: absolute;
top: 0;
right: 0;
font-size: 16px;
color: $dark_gray;
cursor: pointer;
user-select: none;
}
}
</style>
头部信息退出登录
E:\dongli\power-supervision-system\src\views\layout\components\Header.vue
<template>
<div class="header">
<div class="logo">{{title}}</div>
<!-- 折叠按钮 -->
<!-- <div class="collapse-btn" @click="collapseChage">
<i v-if="!collapse" class="iconfont icon-fold"></i>
<i v-else class="iconfont icon-unfold"></i>
</div> -->
<div class="header-right">
<div class="header-user-con">
<!-- 消息中心 -->
<!-- <div class="btn-bell">
<el-tooltip
effect="dark"
:content="message?`有${message}条未读消息`:`消息中心`"
placement="bottom"
>
<router-link to="/tabs">
<i class="el-icon-bell"></i>
</router-link>
</el-tooltip>
<span class="btn-bell-badge" v-if="message"></span>
</div> -->
<!-- 用户头像 -->
<div class="user-avator">
<img class="userImg" src="@/assets/img/user.png" />
</div>
<!-- 用户名下拉菜单 -->
<el-dropdown class="user-name" trigger="click" @command="handleCommand">
<span class="el-dropdown-link">
{{username}}
<i class="el-icon-caret-bottom"></i>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item divided command="loginout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
</div>
</template>
<script>
import Auth from '@/utils/auth'
export default {
data() {
return {
fullscreen: false,
name: "",
message: 2
};
},
computed: {
username() {
let username = localStorage.getItem("username");
return username ? username : this.name;
},
collapse() {
return this.$store.state.collapse;
},
title() {
return window.g.title;
}
},
methods: {
// 用户名下拉菜单选择事件
handleCommand(command) {
if (command == "loginout") {
localStorage.removeItem("username");
localStorage.removeItem("userId");
Auth.removeToken()
this.$router.push("/login");
}
},
// 侧边栏折叠
collapseChage() {
this.$store.commit("hadndleCollapse", !this.collapse);
}
},
mounted() {
if (document.body.clientWidth < 1500) {
this.collapseChage();
}
let username = localStorage.getItem("username");
return username ? username : this.name;
}
};
</script>
<style lang="scss" scoped>
.header {
position: relative;
box-sizing: border-box;
width: 100%;
height: 70px;
font-size: 22px;
color: #fff;
box-shadow: 10px 10px 5px #888888;
}
.collapse-btn {
float: left;
padding: 0 20px;
cursor: pointer;
line-height: 70px;
i.iconfont {
font-size: 20px;
}
}
.header .logo {
float: left;
width: 250px;
line-height: 70px;
text-align: center;
background-color: #18223d;
}
.header-right {
float: right;
padding-right: 50px;
}
.header-user-con {
display: flex;
height: 70px;
align-items: center;
}
.btn-fullscreen {
transform: rotate(45deg);
margin-right: 5px;
font-size: 24px;
}
.btn-bell,
.btn-fullscreen {
position: relative;
width: 30px;
height: 30px;
text-align: center;
border-radius: 15px;
cursor: pointer;
}
.btn-bell-badge {
position: absolute;
right: 0;
top: -2px;
width: 8px;
height: 8px;
border-radius: 4px;
background: #f56c6c;
color: #fff;
}
.btn-bell .el-icon-bell {
color: #fff;
}
.user-name {
margin-left: 10px;
}
.user-avator {
margin-left: 20px;
}
.user-avator img {
display: block;
width: 28px;
height: 28px;
border-radius: 50%;
}
.el-dropdown-link {
// color: #fff;
cursor: pointer;
}
.el-dropdown-menu__item {
text-align: center;
}
</style>