From e6f4b20a1c99c8cff729c73f237eaae71a381604 Mon Sep 17 00:00:00 2001 From: RuoYi Date: Fri, 20 Mar 2026 22:13:44 +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 --- src/api/login.ts | 9 + src/layout/components/Navbar.vue | 18 +- src/permission.ts | 8 + src/router/index.ts | 6 + src/store/modules/lock.ts | 32 +++ src/store/modules/user.ts | 2 + src/views/lock.vue | 374 +++++++++++++++++++++++++++++++ 7 files changed, 448 insertions(+), 1 deletion(-) create mode 100644 src/store/modules/lock.ts create mode 100644 src/views/lock.vue diff --git a/src/api/login.ts b/src/api/login.ts index a2e4149..399e5e4 100644 --- a/src/api/login.ts +++ b/src/api/login.ts @@ -40,6 +40,15 @@ export function getInfo(): Promise { }) } +// 解锁屏幕 +export function unlockScreen(password: string) { + return request({ + url: '/unlockscreen', + method: 'post', + data: { password } + }) +} + // 退出方法 export function logout() { return request({ diff --git a/src/layout/components/Navbar.vue b/src/layout/components/Navbar.vue index 2ce4a13..db9e5eb 100644 --- a/src/layout/components/Navbar.vue +++ b/src/layout/components/Navbar.vue @@ -50,7 +50,10 @@ 布局设置 - + + + 锁定屏幕 + 退出登录 @@ -75,11 +78,15 @@ import RuoYiGit from '@/components/RuoYi/Git/index.vue' import RuoYiDoc from '@/components/RuoYi/Doc/index.vue' import useAppStore from '@/store/modules/app' import useUserStore from '@/store/modules/user' +import useLockStore from '@/store/modules/lock' import useSettingsStore from '@/store/modules/settings' import HeaderNotice from './HeaderNotice' +const route = useRoute() +const router = useRouter() const appStore = useAppStore() const userStore = useUserStore() +const lockStore = useLockStore() const settingsStore = useSettingsStore() function toggleSideBar(): void { @@ -91,6 +98,9 @@ function handleCommand(command: string): void { case "setLayout": setLayout() break + case "lockScreen": + lockScreen() + break case "logout": logout() break @@ -116,6 +126,12 @@ function setLayout(): void { emits('setLayout') } +function lockScreen() { + const currentPath = route.fullPath + lockStore.lockScreen(currentPath) + router.push('/lock') +} + async function toggleTheme(event?: MouseEvent): Promise { const x = event?.clientX || window.innerWidth / 2 const y = event?.clientY || window.innerHeight / 2 diff --git a/src/permission.ts b/src/permission.ts index 0c19318..421c41a 100644 --- a/src/permission.ts +++ b/src/permission.ts @@ -6,6 +6,7 @@ import { getToken } from '@/utils/auth' import { isHttp, isPathMatch } from '@/utils/validate' import { isRelogin } from '@/utils/request' import useUserStore from '@/store/modules/user' +import useLockStore from '@/store/modules/lock' import useSettingsStore from '@/store/modules/settings' import usePermissionStore from '@/store/modules/permission' @@ -21,12 +22,19 @@ router.beforeEach((to, from, next) => { NProgress.start() if (getToken()) { to.meta.title && useSettingsStore().setTitle(to.meta.title as string) + const isLock = useLockStore().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 (useUserStore().roles.length === 0) { isRelogin.show = true diff --git a/src/router/index.ts b/src/router/index.ts index 5b89721..cc5965f 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -70,6 +70,12 @@ export const constantRoutes = [ } ] }, + { + path: '/lock', + component: () => import('@/views/lock.vue'), + hidden: true, + meta: { title: '锁定屏幕' } + }, { path: '/user', component: Layout, diff --git a/src/store/modules/lock.ts b/src/store/modules/lock.ts new file mode 100644 index 0000000..73b000a --- /dev/null +++ b/src/store/modules/lock.ts @@ -0,0 +1,32 @@ +const LOCK_KEY = 'screen-lock' +const LOCK_PATH_KEY = 'screen-lock-path' + +interface LockState { + isLock: boolean + lockPath: string +} + +export const useLockStore = defineStore('lock', { + state: (): LockState => ({ + isLock: JSON.parse(localStorage.getItem(LOCK_KEY) || 'false'), + lockPath: localStorage.getItem(LOCK_PATH_KEY) || '/index' + }), + actions: { + // 锁定屏幕,同时记录当前路径 + lockScreen(currentPath: string) { + this.lockPath = currentPath || '/index' + localStorage.setItem(LOCK_PATH_KEY, this.lockPath) + this.isLock = true + localStorage.setItem(LOCK_KEY, 'true') + }, + // 解锁屏幕,清除路径 + unlockScreen() { + this.isLock = false + localStorage.setItem(LOCK_KEY, 'false') + this.lockPath = '/index' + localStorage.setItem(LOCK_PATH_KEY, '/index') + } + } +}) + +export default useLockStore diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index 9ff4a82..81ae263 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -3,6 +3,7 @@ import { ElMessageBox } from 'element-plus' import { login, logout, getInfo } from '@/api/login' import { getToken, setToken, removeToken } from '@/utils/auth' import { isHttp, isEmpty } from "@/utils/validate" +import useLockStore from '@/store/modules/lock' import defAva from '@/assets/images/profile.jpg' interface UserState { @@ -38,6 +39,7 @@ const useUserStore = defineStore( login(username, password, code, uuid).then(res => { setToken(res.token) this.token = res.token + useLockStore().unlockScreen() resolve() }).catch(error => { reject(error) diff --git a/src/views/lock.vue b/src/views/lock.vue new file mode 100644 index 0000000..b8da429 --- /dev/null +++ b/src/views/lock.vue @@ -0,0 +1,374 @@ + + + + +