```
feat(layout): 添加路由视图刷新功能 - 在 BasicLayout 中添加 viewKey 响应式变量用于控制 router-view 的重新挂载 - 监听自定义 'app:refresh-view' 事件实现页面刷新功能 - 修改 router-view 组件 key 值为 viewKey + '-' + r.fullPath 实现条件渲染 feat(tabs-nav): 优化标签页操作功能 - 添加 handleRefresh 方法通过 dispatchEvent 触发页面刷新事件 - 实现 handleCloseOthers、handleCloseRight、handleCloseAll 方法 - 优化 handleTabClick 避免重复点击当前路由 - 移除无用的激活状态小圆点和右键菜单注释代码 refactor(mock): 调整 mock 数据导入逻辑 - 将 import.meta.env.DEV 条件判断改为直接导入,简化代码结构 ```
This commit is contained in:
parent
1701bdb800
commit
3dd146f871
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, onBeforeUnmount } from 'vue'
|
import { computed, onMounted, onBeforeUnmount, ref, nextTick } from 'vue'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import {
|
import {
|
||||||
Expand,
|
Expand,
|
||||||
|
|
@ -24,6 +24,16 @@ const userStore = useUserStore()
|
||||||
|
|
||||||
const collapsed = computed(() => appStore.sidebarCollapsed)
|
const collapsed = computed(() => appStore.sidebarCollapsed)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路由视图刷新控制:监听 TabsNav 派发的 'app:refresh-view' 事件
|
||||||
|
* 通过 v-if 短暂卸载再挂载 router-view,达到刷新当前页面的效果
|
||||||
|
*/
|
||||||
|
const viewKey = ref(0)
|
||||||
|
|
||||||
|
function onRefreshView() {
|
||||||
|
viewKey.value++
|
||||||
|
}
|
||||||
|
|
||||||
function toggleSidebar() {
|
function toggleSidebar() {
|
||||||
appStore.toggleSidebar()
|
appStore.toggleSidebar()
|
||||||
}
|
}
|
||||||
|
|
@ -37,9 +47,11 @@ function onResize() {
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
onResize()
|
onResize()
|
||||||
window.addEventListener('resize', onResize)
|
window.addEventListener('resize', onResize)
|
||||||
|
window.addEventListener('app:refresh-view', onRefreshView)
|
||||||
})
|
})
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
window.removeEventListener('resize', onResize)
|
window.removeEventListener('resize', onResize)
|
||||||
|
window.removeEventListener('app:refresh-view', onRefreshView)
|
||||||
})
|
})
|
||||||
|
|
||||||
async function handleCommand(cmd: string) {
|
async function handleCommand(cmd: string) {
|
||||||
|
|
@ -122,7 +134,7 @@ async function handleCommand(cmd: string) {
|
||||||
<router-view v-slot="{ Component, route: r }">
|
<router-view v-slot="{ Component, route: r }">
|
||||||
<transition name="slide-up" mode="out-in">
|
<transition name="slide-up" mode="out-in">
|
||||||
<keep-alive>
|
<keep-alive>
|
||||||
<component :is="Component" :key="r.fullPath" />
|
<component :is="Component" :key="viewKey + '-' + r.fullPath" />
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
</transition>
|
</transition>
|
||||||
</router-view>
|
</router-view>
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ watch(
|
||||||
)
|
)
|
||||||
|
|
||||||
function handleTabClick(path: string) {
|
function handleTabClick(path: string) {
|
||||||
|
if (path === route.path) return
|
||||||
tabsStore.setActive(path)
|
tabsStore.setActive(path)
|
||||||
router.push(path)
|
router.push(path)
|
||||||
}
|
}
|
||||||
|
|
@ -30,15 +31,26 @@ function handleClose(e: MouseEvent, path: string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新当前页 — 通过自定义事件通知 BasicLayout 重新挂载 <router-view>
|
||||||
|
* 不使用 router.replace({ path: '/redirect' + ... }),因为我们没有注册 /redirect/* 路由
|
||||||
|
* 会触发通配符跳到 /404
|
||||||
|
*/
|
||||||
function handleRefresh() {
|
function handleRefresh() {
|
||||||
// 通过重新挂载组件模拟刷新
|
window.dispatchEvent(new CustomEvent('app:refresh-view'))
|
||||||
router.replace({ path: '/redirect' + route.path })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 右键菜单
|
function handleCloseOthers() {
|
||||||
function showContextMenu(e: MouseEvent, path: string) {
|
tabsStore.closeOthers(route.path)
|
||||||
e.preventDefault()
|
}
|
||||||
// 简化处理:弹出 el-dropdown(通过 ref 触发)
|
|
||||||
|
function handleCloseRight() {
|
||||||
|
tabsStore.closeRight(route.path)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleCloseAll() {
|
||||||
|
tabsStore.closeAll()
|
||||||
|
router.push('/dashboard')
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -51,10 +63,8 @@ function showContextMenu(e: MouseEvent, path: string) {
|
||||||
:class="['tab-item', { active: tab.path === tabsStore.activeTab }]"
|
:class="['tab-item', { active: tab.path === tabsStore.activeTab }]"
|
||||||
@click="handleTabClick(tab.path)"
|
@click="handleTabClick(tab.path)"
|
||||||
>
|
>
|
||||||
<!-- 激活状态的小圆点 -->
|
|
||||||
<span v-if="tab.path === tabsStore.activeTab" class="tab-dot" />
|
<span v-if="tab.path === tabsStore.activeTab" class="tab-dot" />
|
||||||
<span class="tab-title">{{ tab.title }}</span>
|
<span class="tab-title">{{ tab.title }}</span>
|
||||||
<!-- 非首页才显示关闭按钮 -->
|
|
||||||
<el-icon
|
<el-icon
|
||||||
v-if="tab.path !== '/dashboard'"
|
v-if="tab.path !== '/dashboard'"
|
||||||
class="tab-close"
|
class="tab-close"
|
||||||
|
|
@ -65,7 +75,6 @@ function showContextMenu(e: MouseEvent, path: string) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 右侧操作按钮 -->
|
|
||||||
<div class="tabs-actions">
|
<div class="tabs-actions">
|
||||||
<el-tooltip content="刷新当前页" placement="bottom">
|
<el-tooltip content="刷新当前页" placement="bottom">
|
||||||
<el-button text size="small" :icon="RefreshRight" @click="handleRefresh" />
|
<el-button text size="small" :icon="RefreshRight" @click="handleRefresh" />
|
||||||
|
|
@ -78,15 +87,9 @@ function showContextMenu(e: MouseEvent, path: string) {
|
||||||
</el-button>
|
</el-button>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-item @click="tabsStore.closeOthers(route.path)">
|
<el-dropdown-item @click="handleCloseOthers">关闭其他</el-dropdown-item>
|
||||||
关闭其他
|
<el-dropdown-item @click="handleCloseRight">关闭右侧</el-dropdown-item>
|
||||||
</el-dropdown-item>
|
<el-dropdown-item divided @click="handleCloseAll">关闭所有</el-dropdown-item>
|
||||||
<el-dropdown-item @click="tabsStore.closeRight(route.path)">
|
|
||||||
关闭右侧
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item divided @click="tabsStore.closeAll(); router.push('/dashboard')">
|
|
||||||
关闭所有
|
|
||||||
</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ import './assets/styles/main.scss'
|
||||||
import './permission'
|
import './permission'
|
||||||
|
|
||||||
// Mock 拦截(开发阶段用本地假数据,启动后端后可注释此行)
|
// Mock 拦截(开发阶段用本地假数据,启动后端后可注释此行)
|
||||||
import.meta.env.DEV && import('./mock')
|
import './mock'
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue