From 06f6d1b47f12e4f52d42f8404186062b46b7ea07 Mon Sep 17 00:00:00 2001 From: RuoYi Date: Sat, 21 Mar 2026 23:30:00 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=94=81=E5=AE=9A=E5=B1=8F?= =?UTF-8?q?=E5=B9=95=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/controller/TokenController.java | 11 + .../java/com/ruoyi/auth/form/UnLockBody.java | 24 ++ .../ruoyi/auth/service/SysLoginService.java | 29 ++ ruoyi-ui/src/api/login.js | 9 + ruoyi-ui/src/layout/components/Navbar.vue | 14 +- ruoyi-ui/src/permission.js | 7 + ruoyi-ui/src/router/index.js | 6 + ruoyi-ui/src/store/getters.js | 2 + ruoyi-ui/src/store/index.js | 2 + ruoyi-ui/src/store/modules/lock.js | 34 ++ ruoyi-ui/src/store/modules/user.js | 2 + ruoyi-ui/src/views/lock.vue | 375 ++++++++++++++++++ 12 files changed, 510 insertions(+), 5 deletions(-) create mode 100644 ruoyi-auth/src/main/java/com/ruoyi/auth/form/UnLockBody.java create mode 100644 ruoyi-ui/src/store/modules/lock.js create mode 100644 ruoyi-ui/src/views/lock.vue diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/controller/TokenController.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/controller/TokenController.java index c21dee562..beb861529 100644 --- a/ruoyi-auth/src/main/java/com/ruoyi/auth/controller/TokenController.java +++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/controller/TokenController.java @@ -8,6 +8,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.auth.form.LoginBody; import com.ruoyi.auth.form.RegisterBody; +import com.ruoyi.auth.form.UnLockBody; import com.ruoyi.auth.service.SysLoginService; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.utils.JwtUtils; @@ -75,4 +76,14 @@ public class TokenController sysLoginService.register(registerBody.getUsername(), registerBody.getPassword()); return R.ok(); } + + /** + * 解锁屏幕 + */ + @PostMapping("/unlockscreen") + public R unlockScreen(@RequestBody UnLockBody unLockBody) + { + sysLoginService.unlock(unLockBody.getPassword()); + return R.ok(); + } } diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/form/UnLockBody.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/form/UnLockBody.java new file mode 100644 index 000000000..7421e7782 --- /dev/null +++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/form/UnLockBody.java @@ -0,0 +1,24 @@ +package com.ruoyi.auth.form; + +/** + * 系统解锁对象 + * + * @author ruoyi + */ +public class UnLockBody +{ + /** + * 用户密码 + */ + private String password; + + public String getPassword() + { + return password; + } + + public void setPassword(String password) + { + this.password = password; + } +} diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java index 9ba6046a3..907ffdff0 100644 --- a/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java +++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java @@ -113,11 +113,40 @@ public class SysLoginService remoteUserService.recordUserLogin(sysUser, SecurityConstants.INNER); } + /** + * 退出 + */ public void logout(String loginName) { recordLogService.recordLogininfor(loginName, Constants.LOGOUT, "退出成功"); } + /** + * 解锁 + */ + public void unlock(String password) + { + String username = SecurityUtils.getUsername(); + // 或密码为空 错误 + if (StringUtils.isEmpty(password)) + { + throw new ServiceException("密码不能为空"); + } + // 查询用户信息 + R userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER); + + if (R.FAIL == userResult.getCode()) + { + throw new ServiceException(userResult.getMsg()); + } + + SysUser user = userResult.getData().getSysUser(); + if (!SecurityUtils.matchesPassword(password, user.getPassword())) + { + throw new ServiceException("密码错误,请重新输入"); + } + } + /** * 注册 */ diff --git a/ruoyi-ui/src/api/login.js b/ruoyi-ui/src/api/login.js index 50d8623fa..5d282dc06 100644 --- a/ruoyi-ui/src/api/login.js +++ b/ruoyi-ui/src/api/login.js @@ -25,6 +25,15 @@ export function register(data) { }) } +// 解锁屏幕 +export function unlockScreen(password) { + return request({ + url: '/auth/unlockscreen', + method: 'post', + data: { password } + }) +} + // 刷新方法 export function refreshToken() { return request({ diff --git a/ruoyi-ui/src/layout/components/Navbar.vue b/ruoyi-ui/src/layout/components/Navbar.vue index f64e554f7..35cf72802 100644 --- a/ruoyi-ui/src/layout/components/Navbar.vue +++ b/ruoyi-ui/src/layout/components/Navbar.vue @@ -40,6 +40,9 @@ 布局设置 + + 锁定屏幕 + 退出登录 @@ -106,6 +109,12 @@ export default { setLayout(event) { this.$emit('setLayout') }, + lockScreen() { + const currentPath = this.$route.fullPath + this.$store.dispatch('lock/lockScreen', currentPath).then(() => { + this.$router.push('/lock') + }) + }, logout() { this.$confirm('确定注销并退出系统吗?', '提示', { confirmButtonText: '确定', @@ -173,11 +182,6 @@ export default { margin-left: 8px; } - .errLog-container { - display: inline-block; - vertical-align: top; - } - .right-menu { height: 100%; line-height: 50px; diff --git a/ruoyi-ui/src/permission.js b/ruoyi-ui/src/permission.js index 7b0d1edee..1dac2504e 100644 --- a/ruoyi-ui/src/permission.js +++ b/ruoyi-ui/src/permission.js @@ -19,12 +19,19 @@ router.beforeEach((to, from, next) => { NProgress.start() if (getToken()) { to.meta.title && store.dispatch('settings/setTitle', to.meta.title) + const isLock = store.getters.isLock /* has token*/ if (to.path === '/login') { next({ path: '/' }) NProgress.done() } else if (isWhiteList(to.path)) { next() + } else if (isLock && to.path !== '/lock') { + next({ path: '/lock' }) + NProgress.done() + } else if (!isLock && to.path === '/lock') { + next({ path: '/' }) + NProgress.done() } else { if (store.getters.roles.length === 0) { isRelogin.show = true diff --git a/ruoyi-ui/src/router/index.js b/ruoyi-ui/src/router/index.js index 958ca4b85..f4e884a21 100644 --- a/ruoyi-ui/src/router/index.js +++ b/ruoyi-ui/src/router/index.js @@ -74,6 +74,12 @@ export const constantRoutes = [ } ] }, + { + path: '/lock', + component: () => import('@/views/lock'), + hidden: true, + meta: { title: '锁定屏幕' } + }, { path: '/user', component: Layout, diff --git a/ruoyi-ui/src/store/getters.js b/ruoyi-ui/src/store/getters.js index 04e9fe377..5545bb15f 100644 --- a/ruoyi-ui/src/store/getters.js +++ b/ruoyi-ui/src/store/getters.js @@ -3,6 +3,8 @@ const getters = { size: state => state.app.size, device: state => state.app.device, dict: state => state.dict.dict, + isLock: state => state.lock.isLock, + lockPath: state => state.lock.lockPath, visitedViews: state => state.tagsView.visitedViews, cachedViews: state => state.tagsView.cachedViews, token: state => state.user.token, diff --git a/ruoyi-ui/src/store/index.js b/ruoyi-ui/src/store/index.js index 2ee6e43b3..293f5d1d3 100644 --- a/ruoyi-ui/src/store/index.js +++ b/ruoyi-ui/src/store/index.js @@ -1,6 +1,7 @@ import Vue from 'vue' import Vuex from 'vuex' import app from './modules/app' +import lock from './modules/lock' import dict from './modules/dict' import user from './modules/user' import tagsView from './modules/tagsView' @@ -13,6 +14,7 @@ Vue.use(Vuex) const store = new Vuex.Store({ modules: { app, + lock, dict, user, tagsView, diff --git a/ruoyi-ui/src/store/modules/lock.js b/ruoyi-ui/src/store/modules/lock.js new file mode 100644 index 000000000..14e1bd01a --- /dev/null +++ b/ruoyi-ui/src/store/modules/lock.js @@ -0,0 +1,34 @@ +const LOCK_KEY = 'screen-lock' +const LOCK_PATH_KEY = 'screen-lock-path' + +const lock = { + namespaced: true, + state: { + isLock: JSON.parse(localStorage.getItem(LOCK_KEY) || 'false'), + lockPath: localStorage.getItem(LOCK_PATH_KEY) || '/index' + }, + mutations: { + SET_LOCK(state, status) { + state.isLock = status + localStorage.setItem(LOCK_KEY, JSON.stringify(status)) + }, + SET_LOCK_PATH(state, path) { + state.lockPath = path + localStorage.setItem(LOCK_PATH_KEY, path) + } + }, + actions: { + // 锁定屏幕,同时记录当前路径 + lockScreen({ commit }, currentPath) { + commit('SET_LOCK_PATH', currentPath || '/index') + commit('SET_LOCK', true) + }, + // 解锁屏幕,清除路径 + unlockScreen({ commit }) { + commit('SET_LOCK', false) + commit('SET_LOCK_PATH', '/index') + } + } +} + +export default lock diff --git a/ruoyi-ui/src/store/modules/user.js b/ruoyi-ui/src/store/modules/user.js index 1fff75871..18ccf1c0f 100644 --- a/ruoyi-ui/src/store/modules/user.js +++ b/ruoyi-ui/src/store/modules/user.js @@ -1,3 +1,4 @@ +import store from '@/store' import router from '@/router' import { MessageBox, } from 'element-ui' import { login, logout, getInfo, refreshToken } from '@/api/login' @@ -57,6 +58,7 @@ const user = { commit('SET_TOKEN', data.access_token) setExpiresIn(data.expires_in) commit('SET_EXPIRES_IN', data.expires_in) + store.dispatch('lock/unlockScreen') resolve() }).catch(error => { reject(error) diff --git a/ruoyi-ui/src/views/lock.vue b/ruoyi-ui/src/views/lock.vue new file mode 100644 index 000000000..d6abf0853 --- /dev/null +++ b/ruoyi-ui/src/views/lock.vue @@ -0,0 +1,375 @@ + + + + +