From e0ba88d7b09e2d1c6fabc3f249babd78a243cfc6 Mon Sep 17 00:00:00 2001 From: MoeSnowyFox Date: Sat, 20 Sep 2025 23:25:21 +0800 Subject: [PATCH] =?UTF-8?q?feat(layout):=20=E5=AE=9E=E7=8E=B0=E8=B7=AF?= =?UTF-8?q?=E7=94=B1=E9=94=81=E5=AE=9A=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E4=BE=A7=E8=BE=B9=E6=A0=8F=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 `useRouteLock` 组合式函数,用于在表单编辑等场景下锁定路由切换- 在 `AppLayout.vue` 中集成路由锁定逻辑,防止用户误操作离开当前页面 - 优化侧边栏菜单样式,增强可读性与维护性 - 调整代码格式,提升模板和样式部分的可读性 --- frontend/src/components/AppLayout.vue | 90 ++++++++++++++----- .../src/composables/useRouteLock.example.js | 49 ++++++++++ frontend/src/composables/useRouteLock.ts | 50 +++++++++++ 3 files changed, 169 insertions(+), 20 deletions(-) create mode 100644 frontend/src/composables/useRouteLock.example.js create mode 100644 frontend/src/composables/useRouteLock.ts diff --git a/frontend/src/components/AppLayout.vue b/frontend/src/components/AppLayout.vue index f6b2794..1833fc4 100644 --- a/frontend/src/components/AppLayout.vue +++ b/frontend/src/components/AppLayout.vue @@ -3,7 +3,10 @@
import { - HomeOutlined, - FileTextOutlined, CalendarOutlined, - UnorderedListOutlined, ControlOutlined, + FileTextOutlined, HistoryOutlined, + HomeOutlined, SettingOutlined, + UnorderedListOutlined, } from '@ant-design/icons-vue' import { computed, h } from 'vue' -import { useRouter, useRoute } from 'vue-router' +import { useRoute, useRouter } from 'vue-router' import { useTheme } from '../composables/useTheme.ts' +import { useRouteLock } from '../composables/useRouteLock.ts' import type { MenuProps } from 'ant-design-vue' const SIDER_WIDTH = 160 @@ -52,6 +56,7 @@ const SIDER_WIDTH = 160 const router = useRouter() const route = useRoute() const { isDark } = useTheme() +const { isRouteLocked, triggerBlockCallback } = useRouteLock() // 工具:生成菜单项 const icon = (Comp: any) => () => h(Comp) @@ -79,54 +84,99 @@ const selectedKeys = computed(() => { const onMenuClick: MenuProps['onClick'] = info => { const target = String(info.key) + + // 检查路由是否被锁定 + if (isRouteLocked.value) { + // 如果路由被锁定,触发回调而不进行路由跳转 + triggerBlockCallback(target) + return + } + if (route.path !== target) router.push(target) } - \ No newline at end of file + diff --git a/frontend/src/composables/useRouteLock.example.js b/frontend/src/composables/useRouteLock.example.js new file mode 100644 index 0000000..668dc50 --- /dev/null +++ b/frontend/src/composables/useRouteLock.example.js @@ -0,0 +1,49 @@ +// 使用示例:在任何组件中使用路由锁定功能 + +import { useRouteLock } from '@/composables/useRouteLock' + +export default { + setup() { + const { lockRoute, unlockRoute, isRouteLocked } = useRouteLock() + + // 示例1:在表单编辑时锁定路由 + const startEditing = () => { + lockRoute(targetRoute => { + // 用户尝试切换路由时的回调 + console.log(`用户尝试切换到 ${targetRoute},但表单正在编辑中`) + + // 可以显示确认对话框 + if (confirm('表单正在编辑中,确定要离开吗?')) { + unlockRoute() // 解锁路由 + // 然后可以手动导航到目标路由 + router.push(targetRoute) + } + }) + } + + // 示例2:保存完成后解锁路由 + const saveForm = async () => { + try { + // 保存逻辑... + await saveData() + + // 保存成功后解锁路由 + unlockRoute() + } catch (error) { + console.error('保存失败', error) + } + } + + // 示例3:取消编辑时解锁路由 + const cancelEdit = () => { + unlockRoute() + } + + return { + startEditing, + saveForm, + cancelEdit, + isRouteLocked, + } + }, +} diff --git a/frontend/src/composables/useRouteLock.ts b/frontend/src/composables/useRouteLock.ts new file mode 100644 index 0000000..a68971f --- /dev/null +++ b/frontend/src/composables/useRouteLock.ts @@ -0,0 +1,50 @@ +import { ref } from 'vue' + +type RouteBlockCallback = (targetRoute: string) => void + +const isRouteLocked = ref(false) +let blockCallback: RouteBlockCallback | null = null + +export function useRouteLock() { + /** + * 锁定路由切换 + * @param callback 当用户尝试切换路由时的回调函数 + */ + const lockRoute = (callback: RouteBlockCallback) => { + isRouteLocked.value = true + blockCallback = callback + } + + /** + * 解锁路由切换 + */ + const unlockRoute = () => { + isRouteLocked.value = false + blockCallback = null + } + + /** + * 检查路由是否被锁定 + */ + const checkRouteLocked = () => { + return isRouteLocked.value + } + + /** + * 触发路由阻止回调 + * @param targetRoute 用户尝试访问的目标路由 + */ + const triggerBlockCallback = (targetRoute: string) => { + if (blockCallback) { + blockCallback(targetRoute) + } + } + + return { + isRouteLocked, + lockRoute, + unlockRoute, + checkRouteLocked, + triggerBlockCallback, + } +}