From 06f5d5686dfae5c2ce4da766d69f873b694d0a8d Mon Sep 17 00:00:00 2001 From: Laychen <37046689+Layczm@users.noreply.github.com> Date: Fri, 12 Jul 2024 12:14:09 +0800 Subject: [PATCH] feat: add the ability to lock the screen (#30) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 锁屏功能 * feat: 锁屏样式调整 * feat: complete the lock-screen screen and support shortcut keys and preference configuration --------- Co-authored-by: vince --- apps/web-antd/src/layouts/basic.vue | 34 +++- .../web-antd/src/router/routes/_essentials.ts | 2 +- apps/web-antd/src/store/index.ts | 4 +- apps/web-antd/src/store/modules/app.ts | 42 +++-- .../@core/forward/preferences/src/config.ts | 3 +- .../@core/forward/preferences/src/types.ts | 6 +- .../preferences/src/use-preferences.ts | 6 + packages/@core/locales/src/langs/en-US.json | 13 +- packages/@core/locales/src/langs/zh-CN.json | 13 +- .../@core/shared/design/src/scss-bem/bem.scss | 2 +- .../@core/shared/iconify/src/create-icon.ts | 9 +- packages/@core/shared/iconify/src/material.ts | 2 + .../business/layouts/src/basic/layout.vue | 5 +- .../business/layouts/src/widgets/index.ts | 1 + .../layouts/src/widgets/lock-screen/index.ts | 2 + .../widgets/lock-screen/lock-screen-modal.vue | 106 +++++++++++ .../src/widgets/lock-screen/lock-screen.vue | 170 ++++++++++++++++++ .../src/widgets/lock-screen/typings.ts | 9 + .../preferences/blocks/layout/widget.vue | 4 + .../blocks/shortcut-keys/global.vue | 14 +- .../widgets/preferences/preferences-sheet.vue | 6 + .../src/widgets/preferences/preferences.vue | 4 +- .../widgets/user-dropdown/user-dropdown.vue | 57 +++++- .../src/authentication/code-login.vue | 4 +- .../src/authentication/forget-password.vue | 4 +- .../src/authentication/qrcode-login.vue | 4 +- .../src/authentication/register.vue | 4 +- 27 files changed, 482 insertions(+), 48 deletions(-) create mode 100644 packages/business/layouts/src/widgets/lock-screen/index.ts create mode 100644 packages/business/layouts/src/widgets/lock-screen/lock-screen-modal.vue create mode 100644 packages/business/layouts/src/widgets/lock-screen/lock-screen.vue create mode 100644 packages/business/layouts/src/widgets/lock-screen/typings.ts diff --git a/apps/web-antd/src/layouts/basic.vue b/apps/web-antd/src/layouts/basic.vue index 3c2178e9..c9af11b1 100644 --- a/apps/web-antd/src/layouts/basic.vue +++ b/apps/web-antd/src/layouts/basic.vue @@ -1,11 +1,12 @@ - diff --git a/apps/web-antd/src/router/routes/_essentials.ts b/apps/web-antd/src/router/routes/_essentials.ts index 0965912b..bd3f45e7 100644 --- a/apps/web-antd/src/router/routes/_essentials.ts +++ b/apps/web-antd/src/router/routes/_essentials.ts @@ -51,7 +51,7 @@ const essentialsRoutes: RouteRecordRaw[] = [ component: () => import('#/views/_essential/authentication/code-login.vue'), meta: { - title: $t('page.essentials.code-login'), + title: $t('page.essentials.codeLogin'), }, }, { diff --git a/apps/web-antd/src/store/index.ts b/apps/web-antd/src/store/index.ts index 593e4fd6..4deb7341 100644 --- a/apps/web-antd/src/store/index.ts +++ b/apps/web-antd/src/store/index.ts @@ -2,7 +2,7 @@ import type { InitStoreOptions } from '@vben-core/stores'; import type { App } from 'vue'; -import { initStore } from '@vben-core/stores'; +import { initStore, storeToRefs } from '@vben-core/stores'; /** * @zh_CN 初始化pinia @@ -13,7 +13,7 @@ async function setupStore(app: App, options: InitStoreOptions) { app.use(pinia); } -export { setupStore }; +export { setupStore, storeToRefs }; export { useAccessStore } from './modules/access'; export { useAppStore } from './modules/app'; diff --git a/apps/web-antd/src/store/modules/app.ts b/apps/web-antd/src/store/modules/app.ts index 97a0b642..46b0fcd6 100644 --- a/apps/web-antd/src/store/modules/app.ts +++ b/apps/web-antd/src/store/modules/app.ts @@ -4,19 +4,35 @@ import { defineStore } from 'pinia'; import { useAccessStore } from './access'; -export const useAppStore = defineStore('app', () => { - const accessStore = useAccessStore(); - const coreTabbarStore = useCoreTabbarStore(); +interface AppState { + isLockScreen: boolean; + lockScreenPassword?: string; +} - /** - * 重置所有状态 - */ - async function resetAppState() { - accessStore.reset(); - coreTabbarStore.$reset(); - } +export const useAppStore = defineStore('app', { + actions: { + lockScreen(password: string) { + this.isLockScreen = true; + this.lockScreenPassword = password; + }, - return { - resetAppState, - }; + resetAppState() { + const accessStore = useAccessStore(); + const coreTabbarStore = useCoreTabbarStore(); + accessStore.reset(); + coreTabbarStore.$reset(); + }, + + unlockScreen() { + this.isLockScreen = false; + this.lockScreenPassword = undefined; + }, + }, + persist: { + paths: ['isLockScreen', 'lockScreenPassword'], + }, + state: (): AppState => ({ + isLockScreen: false, + lockScreenPassword: undefined, + }), }); diff --git a/packages/@core/forward/preferences/src/config.ts b/packages/@core/forward/preferences/src/config.ts index 998d0c2d..4ef14f78 100644 --- a/packages/@core/forward/preferences/src/config.ts +++ b/packages/@core/forward/preferences/src/config.ts @@ -3,7 +3,6 @@ import type { Preferences } from './types'; const defaultPreferences: Preferences = { app: { accessMode: 'frontend', - aiAssistant: true, authPageLayout: 'panel-right', colorGrayMode: false, colorWeakMode: false, @@ -55,6 +54,7 @@ const defaultPreferences: Preferences = { }, shortcutKeys: { enable: true, + globalLockScreen: true, globalLogout: true, globalPreferences: true, globalSearch: true, @@ -95,6 +95,7 @@ const defaultPreferences: Preferences = { fullscreen: true, globalSearch: true, languageToggle: true, + lockScreen: true, notification: true, sidebarToggle: true, themeToggle: true, diff --git a/packages/@core/forward/preferences/src/types.ts b/packages/@core/forward/preferences/src/types.ts index bd6297a2..3638cac7 100644 --- a/packages/@core/forward/preferences/src/types.ts +++ b/packages/@core/forward/preferences/src/types.ts @@ -26,8 +26,6 @@ type AuthPageLayoutType = 'panel-center' | 'panel-left' | 'panel-right'; interface AppPreferences { /** 权限模式 */ accessMode: AccessModeType; - /** 是否开启vben助手 */ - aiAssistant: boolean; /** 登录注册页面布局 */ authPageLayout: AuthPageLayoutType; /** 是否开启灰色模式 */ @@ -136,6 +134,8 @@ interface SidebarPreferences { interface ShortcutKeyPreferences { /** 是否启用快捷键-全局 */ enable: boolean; + /** 是否启用全局锁屏快捷键 */ + globalLockScreen: boolean; /** 是否启用全局注销快捷键 */ globalLogout: boolean; /** 是否启用全局偏好设置快捷键 */ @@ -194,6 +194,8 @@ interface WidgetPreferences { globalSearch: boolean; /** 是否启用语言切换部件 */ languageToggle: boolean; + /** 是否开启锁屏功能 */ + lockScreen: boolean; /** 是否显示通知部件 */ notification: boolean; /** 是否显示侧边栏显示/隐藏部件 */ diff --git a/packages/@core/forward/preferences/src/use-preferences.ts b/packages/@core/forward/preferences/src/use-preferences.ts index c43606a7..2eac7a70 100644 --- a/packages/@core/forward/preferences/src/use-preferences.ts +++ b/packages/@core/forward/preferences/src/use-preferences.ts @@ -125,6 +125,11 @@ function usePreferences() { return enable && globalLogout; }); + const globalLockScreenShortcutKey = computed(() => { + const { enable, globalLockScreen } = shortcutKeysPreferences.value; + return enable && globalLockScreen; + }); + /** * @zh_CN 是否启用全局偏好设置快捷键 */ @@ -138,6 +143,7 @@ function usePreferences() { authPanelLeft, authPanelRight, diffPreference, + globalLockScreenShortcutKey, globalLogoutShortcutKey, globalPreferencesShortcutKey, globalSearchShortcutKey, diff --git a/packages/@core/locales/src/langs/en-US.json b/packages/@core/locales/src/langs/en-US.json index d650cb77..e7ad4f21 100644 --- a/packages/@core/locales/src/langs/en-US.json +++ b/packages/@core/locales/src/langs/en-US.json @@ -68,6 +68,16 @@ "noResults": "No Search Results Found", "noRecent": "No Search History", "recent": "Search History" + }, + "lockScreen": { + "title": "Lock Screen", + "screenButton": "Locking", + "password": "Password", + "placeholder": "Please enter password", + "unlock": "Click to unlock", + "errorPasswordTip": "Password error, please re-enter", + "backToLogin": "Back to login", + "entry": "Enter the system" } }, "authentication": { @@ -263,7 +273,8 @@ "languageToggle": "Enable Language Toggle", "notification": "Enable Notification", "sidebarToggle": "Enable Sidebar Toggle", - "aiAssistant": "Enable AI Assistant" + "aiAssistant": "Enable AI Assistant", + "lockScreen": "Enable Lock Screen" } } } diff --git a/packages/@core/locales/src/langs/zh-CN.json b/packages/@core/locales/src/langs/zh-CN.json index 6dd6aad8..6d317a13 100644 --- a/packages/@core/locales/src/langs/zh-CN.json +++ b/packages/@core/locales/src/langs/zh-CN.json @@ -68,6 +68,16 @@ "noResults": "未找到搜索结果", "noRecent": "没有搜索历史", "recent": "搜索历史" + }, + "lockScreen": { + "title": "锁定屏幕", + "screenButton": "锁定", + "password": "密码", + "placeholder": "请输入锁屏密码", + "unlock": "点击解锁", + "errorPasswordTip": "密码错误,请重新输入", + "backToLogin": "返回登录", + "entry": "进入系统" } }, "authentication": { @@ -263,7 +273,8 @@ "languageToggle": "启用语言切换", "notification": "启用通知", "sidebarToggle": "启用侧边栏切换", - "aiAssistant": "启用 AI 助手" + "aiAssistant": "启用 AI 助手", + "lockScreen": "启用锁屏" } } } diff --git a/packages/@core/shared/design/src/scss-bem/bem.scss b/packages/@core/shared/design/src/scss-bem/bem.scss index 2c8ec306..3910a305 100644 --- a/packages/@core/shared/design/src/scss-bem/bem.scss +++ b/packages/@core/shared/design/src/scss-bem/bem.scss @@ -1,4 +1,4 @@ -@forward './constants.scss'; +@forward './constants'; @mixin b($block) { $B: $namespace + '-' + $block !global; diff --git a/packages/@core/shared/iconify/src/create-icon.ts b/packages/@core/shared/iconify/src/create-icon.ts index 49a7c805..f108023f 100644 --- a/packages/@core/shared/iconify/src/create-icon.ts +++ b/packages/@core/shared/iconify/src/create-icon.ts @@ -1,9 +1,14 @@ -import { h } from 'vue'; +import { defineComponent, h } from 'vue'; import { Icon } from '@iconify/vue'; function createIconifyIcon(icon: string) { - return h(Icon, { icon }); + return defineComponent({ + name: `SvgIcon-${icon}`, + setup(props, { attrs }) { + return () => h(Icon, { icon, ...props, ...attrs }); + }, + }); } export { createIconifyIcon }; diff --git a/packages/@core/shared/iconify/src/material.ts b/packages/@core/shared/iconify/src/material.ts index d85ea7c4..52a41899 100644 --- a/packages/@core/shared/iconify/src/material.ts +++ b/packages/@core/shared/iconify/src/material.ts @@ -82,3 +82,5 @@ export const IcRoundMultipleStop = createIconifyIcon('ic:round-multiple-stop'); export const IcRoundRefresh = createIconifyIcon('ic:round-refresh'); export const IcRoundCreditScore = createIconifyIcon('ic:round-credit-score'); + +export const IcRoundLock = createIconifyIcon('ic:round-lock'); diff --git a/packages/business/layouts/src/basic/layout.vue b/packages/business/layouts/src/basic/layout.vue index 112c2798..3165b979 100644 --- a/packages/business/layouts/src/basic/layout.vue +++ b/packages/business/layouts/src/basic/layout.vue @@ -279,7 +279,10 @@ function clearPreferencesAndLogout() { diff --git a/packages/business/layouts/src/widgets/index.ts b/packages/business/layouts/src/widgets/index.ts index 718d1a73..c6e5fbd4 100644 --- a/packages/business/layouts/src/widgets/index.ts +++ b/packages/business/layouts/src/widgets/index.ts @@ -4,6 +4,7 @@ export { default as CozeAssistant } from './coze-assistant.vue'; export * from './global-search'; export { default as LanguageToggle } from './language-toggle.vue'; export { default as AuthenticationLayoutToggle } from './layout-toggle.vue'; +export * from './lock-screen'; export * from './notification'; export * from './preferences'; export * from './theme-toggle'; diff --git a/packages/business/layouts/src/widgets/lock-screen/index.ts b/packages/business/layouts/src/widgets/lock-screen/index.ts new file mode 100644 index 00000000..1609becb --- /dev/null +++ b/packages/business/layouts/src/widgets/lock-screen/index.ts @@ -0,0 +1,2 @@ +export { default as LockScreen } from './lock-screen.vue'; +export { default as LockScreenModal } from './lock-screen-modal.vue'; diff --git a/packages/business/layouts/src/widgets/lock-screen/lock-screen-modal.vue b/packages/business/layouts/src/widgets/lock-screen/lock-screen-modal.vue new file mode 100644 index 00000000..72af6f1a --- /dev/null +++ b/packages/business/layouts/src/widgets/lock-screen/lock-screen-modal.vue @@ -0,0 +1,106 @@ + + + diff --git a/packages/business/layouts/src/widgets/lock-screen/lock-screen.vue b/packages/business/layouts/src/widgets/lock-screen/lock-screen.vue new file mode 100644 index 00000000..ad34f9ec --- /dev/null +++ b/packages/business/layouts/src/widgets/lock-screen/lock-screen.vue @@ -0,0 +1,170 @@ + + + diff --git a/packages/business/layouts/src/widgets/lock-screen/typings.ts b/packages/business/layouts/src/widgets/lock-screen/typings.ts new file mode 100644 index 00000000..c06ea750 --- /dev/null +++ b/packages/business/layouts/src/widgets/lock-screen/typings.ts @@ -0,0 +1,9 @@ +interface LockAndRegisterParams { + lockScreenPassword: string; +} + +interface RegisterEmits { + submit: [LockAndRegisterParams]; +} + +export type { LockAndRegisterParams, RegisterEmits }; diff --git a/packages/business/layouts/src/widgets/preferences/blocks/layout/widget.vue b/packages/business/layouts/src/widgets/preferences/blocks/layout/widget.vue index 4107a311..6329c79c 100644 --- a/packages/business/layouts/src/widgets/preferences/blocks/layout/widget.vue +++ b/packages/business/layouts/src/widgets/preferences/blocks/layout/widget.vue @@ -14,6 +14,7 @@ const widgetNotification = defineModel('widgetNotification'); const widgetThemeToggle = defineModel('widgetThemeToggle'); const widgetAiAssistant = defineModel('widgetAiAssistant'); const widgetSidebarToggle = defineModel('widgetSidebarToggle'); +const widgetLockScreen = defineModel('widgetLockScreen'); diff --git a/packages/business/layouts/src/widgets/preferences/preferences-sheet.vue b/packages/business/layouts/src/widgets/preferences/preferences-sheet.vue index 1e846e5f..9a29de27 100644 --- a/packages/business/layouts/src/widgets/preferences/preferences-sheet.vue +++ b/packages/business/layouts/src/widgets/preferences/preferences-sheet.vue @@ -128,6 +128,9 @@ const shortcutKeysGlobalLogout = defineModel( const shortcutKeysGlobalPreferences = defineModel( 'shortcutKeysGlobalPreferences', ); +const shortcutKeysGlobalLockScreen = defineModel( + 'shortcutKeysGlobalLockScreen', +); const widgetGlobalSearch = defineModel('widgetGlobalSearch'); const widgetFullscreen = defineModel('widgetFullscreen'); @@ -136,6 +139,7 @@ const widgetNotification = defineModel('widgetNotification'); const widgetThemeToggle = defineModel('widgetThemeToggle'); const widgetAiAssistant = defineModel('widgetAiAssistant'); const widgetSidebarToggle = defineModel('widgetSidebarToggle'); +const widgetLockScreen = defineModel('widgetLockScreen'); const { diffPreference, @@ -355,6 +359,7 @@ async function handleReset() { v-model:widget-fullscreen="widgetFullscreen" v-model:widget-global-search="widgetGlobalSearch" v-model:widget-language-toggle="widgetLanguageToggle" + v-model:widget-lock-screen="widgetLockScreen" v-model:widget-notification="widgetNotification" v-model:widget-sidebar-toggle="widgetSidebarToggle" v-model:widget-theme-toggle="widgetThemeToggle" @@ -384,6 +389,7 @@ async function handleReset() { + + + {{ $t('widgets.lockScreen.title') }} + + {{ altView }} L + + { {{ $t('common.login') }} - + {{ $t('common.back') }} diff --git a/packages/business/universal-ui/src/authentication/forget-password.vue b/packages/business/universal-ui/src/authentication/forget-password.vue index 8968e2f3..a296199e 100644 --- a/packages/business/universal-ui/src/authentication/forget-password.vue +++ b/packages/business/universal-ui/src/authentication/forget-password.vue @@ -50,7 +50,7 @@ function handleSubmut() { emit('submit', formState.email); } -function goLogin() { +function goToLogin() { router.push(props.loginPath); } @@ -79,7 +79,7 @@ function goLogin() { {{ $t('authentication.sendResetLink') }} - + {{ $t('common.back') }} diff --git a/packages/business/universal-ui/src/authentication/qrcode-login.vue b/packages/business/universal-ui/src/authentication/qrcode-login.vue index 8b4f0dbd..ceafc408 100644 --- a/packages/business/universal-ui/src/authentication/qrcode-login.vue +++ b/packages/business/universal-ui/src/authentication/qrcode-login.vue @@ -39,7 +39,7 @@ const qrcode = useQRCode(text, { margin: 4, }); -function goLogin() { +function goToLogin() { router.push(props.loginPath); } @@ -62,7 +62,7 @@ function goLogin() {

- + {{ $t('common.back') }} diff --git a/packages/business/universal-ui/src/authentication/register.vue b/packages/business/universal-ui/src/authentication/register.vue index c99fd0f5..3969c2f0 100644 --- a/packages/business/universal-ui/src/authentication/register.vue +++ b/packages/business/universal-ui/src/authentication/register.vue @@ -78,7 +78,7 @@ function handleSubmit() { }); } -function goLogin() { +function goToLogin() { router.push(props.loginPath); } @@ -160,7 +160,7 @@ function goLogin() { {{ $t('authentication.alreadyHaveAccount') }} {{ $t('authentication.goToLogin') }}