Vue 担心系统数据泄露?手把手教你实现系统锁屏功能

目录

一、前言

二、效果图

三、实现代码

1、封装组件

2、使用组件

3、修改路由


一、前言

当我们离开电脑不工作时,相信很多人都会有锁屏的习惯。目的当然是不想随随便便让别人使用我们的电脑啦,我们后台管理系统也是同样的道理,有的时候可能暂时离开电脑,我们就可以把系统锁屏,只有知道登录密码才能登录继续使用系统。博主的后台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 ,大家一起学习,一起进步。

发布了70 篇原创文章 · 获赞 60 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/Wjhsmart/article/details/105762784