目錄
一、前言
當我們離開電腦不工作時,相信很多人都會有鎖屏的習慣。目的當然是不想隨隨便便讓別人使用我們的電腦啦,我們後臺管理系統也是同樣的道理,有的時候可能暫時離開電腦,我們就可以把系統鎖屏,只有知道登錄密碼才能登錄繼續使用系統。博主的後臺UI框架使用的是iview-admin。
實現思路:準備一個鎖屏頁面,使用cookie標識當前系統是否是鎖屏狀態,當點擊鎖屏後跳轉到鎖屏頁面,並保留當前的路由頁面到緩存中。同時把標識改爲鎖屏中,當輸入正確的登錄密碼後,把鎖屏標識解鎖,然後回到鎖屏之前的頁面。
二、效果圖
三、實現代碼
1、封裝組件
寫好鎖屏頁面,並封裝成組件。博主的組件目錄結構:
lockscreen.vue 代碼:
<template>
<div @click="lockScreen" class="lock-screen-btn-con">
<Tooltip content="鎖屏" placement="bottom">
<Icon type="md-lock" :size="24"></Icon>
</Tooltip>
</div>
</template>
<script>
import Cookies from "js-cookie";
const setLockBackSize = () => {
let x = document.body.clientWidth;
let y = document.body.clientHeight;
let r = Math.sqrt(x * x + y * y);
return parseInt(r);
};
export default {
name: "lockScreen",
props: {
value: {
type: Boolean,
default: false
}
},
methods: {
lockScreen() {
let lockScreenBack = document.getElementById("lock_screen_back");
lockScreenBack.style.transition = "all 3s";
lockScreenBack.style.zIndex = 10000;
lockScreenBack.style.boxShadow =
"0 0 0 " + this.lockScreenSize + "px #667aa6 inset";
this.showUnlock = true;
Cookies.set("last_page_name", this.$route.name); // 本地存儲鎖屏之前打開的頁面以便解鎖後打開
setTimeout(() => {
lockScreenBack.style.transition = "all 0s";
this.$router.push({
name: "locking"
});
}, 800);
Cookies.set("locking", "1");
}
},
mounted() {
let lockScreenBack;
if (!document.getElementById("lock_screen_back")) {
let lockdiv = document.createElement("div");
lockdiv.setAttribute("id", "lock_screen_back");
lockdiv.setAttribute("class", "lock-screen-back");
document.body.appendChild(lockdiv);
lockScreenBack = document.getElementById("lock_screen_back");
window.addEventListener("resize", () => {
let size = setLockBackSize();
this.lockScreenSize = size;
lockScreenBack.style.transition = "all 0s";
lockScreenBack.style.width = lockScreenBack.style.height = size + "px";
});
} else {
lockScreenBack = document.getElementById("lock_screen_back");
}
let size = setLockBackSize();
this.lockScreenSize = size;
lockScreenBack.style.transition = "all 3s";
lockScreenBack.style.width = lockScreenBack.style.height = size + "px";
}
};
</script>
unlock.less 代碼:
.unlock-body-con{
position: absolute;
width: 400px;
height: 100px;
left: 50%;
top: 50%;
margin-left: -200px;
margin-top: -200px;
transform-origin: center center;
z-index: 10;
.unlock-avator-con{
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
box-sizing: border-box;
width: 100px;
height: 100px;
border-radius: 50%;
overflow: hidden;
border: 2px solid white;
cursor: pointer;
transition: all .5s;
z-index: 12;
box-shadow: 0 0 10px 2px rgba(255, 255, 255, .3);
.unlock-avator-img{
width: 100%;
height: 100%;
display: block;
z-index: 7;
}
.unlock-avator-cover{
width: 100%;
height: 100%;
background: rgba(0, 0, 0, .6);
z-index: 11600;
position: absolute;
left: 0;
top: 0;
opacity: 0;
transition: opacity .2s;
color: white;
span{
display: block;
margin: 20px auto 5px;
text-align: center;
}
p{
text-align: center;
font-size: 16px;
font-weight: 500;
}
}
&:hover .unlock-avator-cover{
opacity: 1;
transition: opacity .2s;
}
}
.unlock-avator-under-back{
position: absolute;
left: 50%;
top: 50%;
transform: translate(-45px,-50%);
box-sizing: border-box;
width: 100px;
height: 100px;
border-radius: 50%;
background: #667aa6;
transition: all .5s;
z-index: 5;
}
.unlock-input-con{
position: absolute;
height: 70px;
width: 350px;
top: 15px;
right: 0px;
.unlock-input-overflow-con{
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
overflow: hidden;
.unlock-overflow-body{
position: absolute;
top: 0;
right: 0;
width: 100%;
height: 100%;
transition: all .5s ease .5s;
.unlock-input{
float: left;
display: block;
box-sizing: content-box;
height: 22px;
width: 230px;
font-size: 18px;
outline: none;
padding: 11px 10px 11px 30px;
border: 2px solid #e2ddde;
margin-top: 10px;
}
.unlock-btn{
float: left;
display: block;
font-size: 20px;
padding: 7px 26px;
cursor: pointer;
border-radius: 0 25px 25px 0;
border: 2px solid #e2ddde;
border-left: none;
background: #2d8cf0;
outline: none;
transition: all .2s;
margin-top: 10px;
&:hover{
background: #5cadff;
box-shadow: 0 0 10px 3px rgba(255, 255, 255, .2);
}
}
.click-unlock-btn{
background: #2b85e4 !important;
}
}
}
}
.unlock-locking-tip-con{
width: 100px;
height: 30px;
text-align: center;
position: absolute;
left: 50%;
margin-left: -50px;
bottom: -80px;
color: white;
font-size: 18px;
}
}
@keyframes unlock-in{
0% {
transform: scale(0);
}
80%{
transform: scale(0);
}
88% {
transform: scale(1.3);
}
100% {
transform: scale(1);
}
}
@keyframes unlock-out{
0% {
transform: scale(1);
}
60%{
transform: scale(1.2);
}
100% {
transform: scale(0);
}
}
.show-unlock-enter-active{
animation: unlock-in 1.4s ease;
}
.show-unlock-leave-to{
opacity: 0;
}
.show-unlock-leave-active{
transition: opacity .2s;
}
.unlock-con{
width: 100%;
height: 100%;
}
locking-page.vue 代碼:
<template>
<div style="width: 100%;height: 100%;background: #667aa6">
<div class="unlock-con">
<unlock :show-unlock="showUnlock" @on-unlock="handleUnlock"></unlock>
</div>
</div>
</template>
<script>
import unlock from './unlock.vue';
import Cookies from 'js-cookie';
export default {
components: {
unlock
},
data () {
return {
showUnlock: false
};
},
methods: {
handleUnlock () {
let lockScreenBack = document.getElementById('lock_screen_back');
this.showUnlock = false;
lockScreenBack.style.zIndex = -1;
lockScreenBack.style.boxShadow = '0 0 0 0 #667aa6 inset';
this.$router.push({
name: Cookies.get('last_page_name') // 解鎖之後跳轉到鎖屏之前的頁面
});
}
},
mounted () {
this.showUnlock = true;
if (!document.getElementById('lock_screen_back')) {
let lockdiv = document.createElement('div');
lockdiv.setAttribute('id', 'lock_screen_back');
lockdiv.setAttribute('class', 'lock-screen-back');
document.body.appendChild(lockdiv);
}
let lockScreenBack = document.getElementById('lock_screen_back');
lockScreenBack.style.zIndex = -1;
}
};
</script>
unlock.vue 代碼:
<style lang="less">
@import "../styles/unlock.less";
</style>
<template>
<transition name="show-unlock">
<div class="unlock-body-con" v-if="showUnlock" @keydown.enter="handleUnlock">
<div @click="handleClickAvator" class="unlock-avator-con" :style="{marginLeft: avatorLeft}">
<img class="unlock-avator-img" :src="avatarPath">
<div class="unlock-avator-cover">
<span><Icon type="md-unlock" :size="30"></Icon></span>
<p>解鎖</p>
</div>
</div>
<div class="unlock-avator-under-back" :style="{marginLeft: avatorLeft}"></div>
<div class="unlock-input-con">
<div class="unlock-input-overflow-con">
<div class="unlock-overflow-body" :style="{right: inputLeft}">
<input ref="inputEle" v-model="password" class="unlock-input" type="password" placeholder="密碼同登錄密碼" />
<button ref="unlockBtn" @mousedown="unlockMousedown" @mouseup="unlockMouseup" @click="handleUnlock" class="unlock-btn"><Icon color="white" type="ios-key"></Icon></button>
</div>
</div>
</div>
<div class="unlock-locking-tip-con">已鎖定</div>
</div>
</transition>
</template>
<script>
import axios from '@/libs/api.request'
import Cookies from "js-cookie"
const localStorage = window.localStorage
export default {
name: "Unlock",
data() {
return {
avatorLeft: "0px",
inputLeft: "400px",
password: "",
check: null
};
},
props: {
showUnlock: {
type: Boolean,
default: false
}
},
computed: {
avatarPath() {
let headUrl = localStorage.getItem('userHeadUrl')
return headUrl;
}
},
methods: {
unlock() {
this.avatorLeft = "0px";
this.inputLeft = "400px";
this.password = "";
Cookies.set("locking", "0");
this.$emit("on-unlock");
},
handleClickAvator() {
this.avatorLeft = "-180px";
this.inputLeft = "0px";
this.$refs.inputEle.focus();
},
handleUnlock() {
if (this.password == "") {
this.$Message.error("請輸入密碼");
return;
}
// 將用戶輸入的密碼this.password與數據庫用戶密碼對比
let flag = false;
axios.request({
url: '/user/admin/vlied-password',
method: 'POST',
data: { password: this.password }
}).then(
res => {
if (res.data.code == '1001') {
this.unlock();
} else {
this.$Message.error(res.data.message)
}
}
);
},
unlockMousedown() {
this.$refs.unlockBtn.className = "unlock-btn click-unlock-btn";
},
unlockMouseup() {
this.$refs.unlockBtn.className = "unlock-btn";
}
}
};
</script>
unlock.vue 文件注意事項:
1、博主的用戶頭像路徑是存儲在 localStorage 裏面,所以此處用到了 localStorage 取用戶頭像。
2、請求後臺驗證用戶密碼這個請求,大家可以根據自己的實際情況換成自己封裝好的請求。
2、使用組件
找到 main.vue 文件,引入組件。
// 引入組件,根據自己組件所在位置修改
import lockScreen from "./components/lockscreen/lockscreen.vue"
// 註冊組件
components: {
lockScreen
},
// 使用組件
<lock-screen style="margin-right: 10px;"></lock-screen>
3、修改路由
需要修改路由的判斷,找到 router 目錄下面的 index.js 文件
找到 beforeEach 方法,增加以下判斷。
router.beforeEach((to, from, next) => {
iView.LoadingBar.start()
if (Cookies.get('locking') == '1' && to.name !== 'locking') {
// 判斷當前是否是鎖定狀態
next({
replace: true,
name: 'locking'
});
} else if (Cookies.get('locking') == '0' && to.name == 'locking') {
next(false);
} else {
// 白名單
const token = getLocalStorageToken()
if (!token && to.name !== LOGIN_PAGE_NAME) {
// 未登錄且要跳轉的頁面不是登錄頁
next({
name: LOGIN_PAGE_NAME // 跳轉到登錄頁
})
} else if (!token && to.name === LOGIN_PAGE_NAME) {
// 未登陸且要跳轉的頁面是登錄頁
next() // 跳轉
} else if (token && to.name === LOGIN_PAGE_NAME) {
// 已登錄且要跳轉的頁面是登錄頁
next({
name: homeName // 跳轉到homeName頁
})
} else {
if (store.state.user.hasGetInfo) {
turnTo(to, store.state.user.access, next)
} else {
store.dispatch('getUserInfo').then(user => {
// 拉取用戶信息,通過用戶權限和跳轉的頁面的name來判斷是否有權限訪問;access必須是一個數組,如:['super_admin'] ['super_admin', 'admin']
turnTo(to, user.access, next)
}).catch(() => {
setToken('')
next({
name: 'login'
})
})
}
}
}
})
到此,就完成了,如果有什麼地方不懂的,可以加V:GZWjhsmart ,大家一起學習,一起進步。