Skip to content

Commit

Permalink
feat: 前端路由固定
Browse files Browse the repository at this point in the history
  • Loading branch information
devhaozi committed Oct 19, 2024
1 parent b94664e commit c75cfe9
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 45 deletions.
12 changes: 9 additions & 3 deletions web/src/layout/AppMain.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
<script lang="ts" setup>
import { useAppStore } from '@/store'
import { useTabStore } from '@/store'
const appStore = useAppStore()
const tabStore = useTabStore()
const keepAliveNames = computed(() => {
return tabStore.tabs.filter((item) => item.keepAlive).map((item) => item.name)
})
</script>

<template>
<router-view v-slot="{ Component, route }">
<component :is="Component" v-if="appStore.reloadFlag" :key="route.path" />
<keep-alive :include="keepAliveNames">
<component :is="Component" v-if="!tabStore.reloading" :key="route.path" />
</keep-alive>
</router-view>
</template>
6 changes: 3 additions & 3 deletions web/src/layout/header/components/ReloadPage.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script lang="ts" setup>
import { useAppStore } from '@/store'
import { useTabStore } from '@/store'
const appStore = useAppStore()
const tabStore = useTabStore()
const handleReloadPage = () => {
appStore.reloadPage()
tabStore.reloadTab(tabStore.active)
}
</script>

Expand Down
7 changes: 4 additions & 3 deletions web/src/layout/sidebar/components/SideMenu.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { useAppStore, usePermissionStore, useThemeStore } from '@/store'
import { usePermissionStore, useTabStore, useThemeStore } from '@/store'
import { isUrl, renderIcon } from '@/utils'
import type { MenuInst, MenuOption } from 'naive-ui'
import type { VNodeChild } from 'vue'
Expand All @@ -11,7 +11,7 @@ const router = useRouter()
const currentRoute = useRoute()
const permissionStore = usePermissionStore()
const themeStore = useThemeStore()
const appStore = useAppStore()
const tabStore = useTabStore()
const menu = ref<MenuInst>()
watch(currentRoute, async () => {
Expand Down Expand Up @@ -93,7 +93,8 @@ function handleMenuSelect(key: string, item: MenuOption) {
window.open(menuItem.path)
return
}
if (menuItem.path === currentRoute.path && !currentRoute.meta?.keepAlive) appStore.reloadPage()
if (menuItem.path === currentRoute.path && !currentRoute.meta?.keepAlive)
tabStore.reloadTab(currentRoute.path)
else router.push(menuItem.path)
// 手机端自动收起菜单
Expand Down
9 changes: 6 additions & 3 deletions web/src/layout/tab/IndexView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ const tabStore = useTabStore()
interface ContextMenuOption {
show: boolean
keepAlive: boolean
x: number
y: number
currentPath: string
}
const contextMenuOption = reactive<ContextMenuOption>({
show: false,
keepAlive: false,
x: 0,
y: 0,
currentPath: ''
Expand All @@ -33,15 +35,15 @@ function hideContextMenu() {
contextMenuOption.show = false
}
function setContextMenu(x: number, y: number, currentPath: string) {
Object.assign(contextMenuOption, { x, y, currentPath })
function setContextMenu(x: number, y: number, keepAlive: boolean, currentPath: string) {
Object.assign(contextMenuOption, { x, y, keepAlive, currentPath })
}
// 右击菜单
async function handleContextMenu(e: MouseEvent, tabItem: TabItem) {
const { clientX, clientY } = e
hideContextMenu()
setContextMenu(clientX, clientY, tabItem.path)
setContextMenu(clientX, clientY, tabItem.keepAlive, tabItem.path)
await nextTick()
showContextMenu()
}
Expand All @@ -68,6 +70,7 @@ async function handleContextMenu(e: MouseEvent, tabItem: TabItem) {
<ContextMenu
v-model:show="contextMenuOption.show"
:current-path="contextMenuOption.currentPath"
:keep-alive="contextMenuOption.keepAlive"
:x="contextMenuOption.x"
:y="contextMenuOption.y"
/>
Expand Down
45 changes: 35 additions & 10 deletions web/src/layout/tab/components/ContextMenu.vue
Original file line number Diff line number Diff line change
@@ -1,36 +1,49 @@
<script lang="ts" setup>
import { useAppStore, useTabStore } from '@/store'
import { useTabStore } from '@/store'
import { renderIcon } from '@/utils'
interface Props {
show?: boolean
keepAlive?: boolean
currentPath?: string
x: number
y: number
}
const props = withDefaults(defineProps<Props>(), {
show: false,
keepAlive: false,
currentPath: ''
})
const emit = defineEmits(['update:show'])
const tabStore = useTabStore()
const appStore = useAppStore()
const options = computed(() => [
{
label: '重新加载',
label: '关闭',
key: 'close',
disabled: tabStore.tabs.length <= 1,
icon: renderIcon('mdi:close', { size: 14 })
},
{
label: '重载',
key: 'reload',
disabled: props.currentPath !== tabStore.active,
icon: renderIcon('mdi:refresh', { size: 14 })
},
{
label: '关闭',
key: 'close',
disabled: tabStore.tabs.length <= 1,
icon: renderIcon('mdi:close', { size: 14 })
label: '固定',
key: 'pin',
disabled: props.keepAlive,
icon: renderIcon('mdi:pin', { size: 14 })
},
{
label: '取消固定',
key: 'unpin',
disabled: !props.keepAlive,
icon: renderIcon('mdi:pin-off', { size: 14 })
},
{
label: '关闭其他',
Expand Down Expand Up @@ -64,16 +77,28 @@ const dropdownShow = computed({
})
const actionMap = new Map([
[
'close',
() => {
tabStore.removeTab(props.currentPath)
}
],
[
'reload',
() => {
appStore.reloadPage()
tabStore.reloadTab(props.currentPath)
}
],
[
'close',
'pin',
() => {
tabStore.removeTab(props.currentPath)
tabStore.pinTab(props.currentPath)
}
],
[
'unpin',
() => {
tabStore.unpinTab(props.currentPath)
}
],
[
Expand Down
3 changes: 2 additions & 1 deletion web/src/router/guard/tab-guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export function createTabGuard(router: Router) {
tabStore.addTab({
name: String(name),
path,
title
title,
keepAlive: false
})
})
}
18 changes: 2 additions & 16 deletions web/src/store/modules/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,7 @@ import { defineStore } from 'pinia'

export const useAppStore = defineStore('app', {
state() {
return {
reloadFlag: <boolean>true
}
return {}
},
actions: {
async reloadPage() {
window.$loadingBar?.start()
this.reloadFlag = false
await nextTick()
this.reloadFlag = true

setTimeout(() => {
document.documentElement.scrollTo({ left: 0, top: 0 })
window.$loadingBar?.finish()
}, 100)
}
}
actions: {}
})
1 change: 0 additions & 1 deletion web/src/store/modules/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export * from './app'
export * from './permission'
export * from './tab'
export * from './theme'
Expand Down
34 changes: 32 additions & 2 deletions web/src/store/modules/tab/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,28 @@ export const WITHOUT_TAB_PATHS = ['/404', '/login']

export interface Tab {
active: string
reloading: boolean
tabs: Array<TabItem>
}

export interface TabItem {
name: string
path: string
title: string
keepAlive: boolean
}

export const useTabStore = defineStore('tab', {
state: (): Tab => {
return {
active: '',
reloading: false,
tabs: []
}
},
actions: {
setActiveTab(path: string) {
async setActiveTab(path: string) {
await nextTick()
this.active = path
},
setTabs(tabs: Array<TabItem>) {
Expand All @@ -34,6 +38,30 @@ export const useTabStore = defineStore('tab', {
return
this.setTabs([...this.tabs, tab])
},
async reloadTab(path: string) {
const findItem = this.tabs.find((item) => item.path === path)
if (!findItem) return
const keepLive = findItem.keepAlive
findItem.keepAlive = false // 取消keepAlive
window.$loadingBar.start()
this.reloading = true
await nextTick()
this.reloading = false
await nextTick()
findItem.keepAlive = keepLive // 恢复keepAlive原状态
setTimeout(() => {
document.documentElement.scrollTo({ left: 0, top: 0 })
window.$loadingBar.finish()
}, 100)
},
pinTab(path: string) {
const findItem = this.tabs.find((item) => item.path === path)
if (findItem) findItem.keepAlive = true
},
unpinTab(path: string) {
const findItem = this.tabs.find((item) => item.path === path)
if (findItem) findItem.keepAlive = false
},
removeTab(path: string) {
if (path === this.active) {
const activeIndex = this.tabs.findIndex((item) => item.path === path)
Expand Down Expand Up @@ -65,5 +93,7 @@ export const useTabStore = defineStore('tab', {
this.setActiveTab('')
}
},
persist: true
persist: {
storage: sessionStorage
}
})
6 changes: 3 additions & 3 deletions web/src/views/home/IndexView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { useI18n } from 'vue-i18n'
import dashboard from '@/api/panel/dashboard'
import { router } from '@/router'
import { useAppStore } from '@/store'
import { useTabStore } from '@/store'
import { formatDateTime, formatDuration, toTimestamp } from '@/utils/common'
import { formatBytes, formatPercent } from '@/utils/file'
import VChart from 'vue-echarts'
Expand All @@ -31,7 +31,7 @@ use([
])
const { locale } = useI18n()
const appStore = useAppStore()
const tabStore = useTabStore()
const realtime = ref<Realtime | null>(null)
const systemInfo = ref<SystemInfo | null>(null)
const homeApps = ref<HomeApp[] | null>(null)
Expand Down Expand Up @@ -310,7 +310,7 @@ const handleRestartPanel = () => {
dashboard.restart().then(() => {
window.$message.success('面板重启成功')
setTimeout(() => {
appStore.reloadPage()
tabStore.reloadTab(tabStore.active)
}, 3000)
})
}
Expand Down
4 changes: 4 additions & 0 deletions web/src/views/website/EditView.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<script setup lang="ts">
defineOptions({
name: 'website-edit'
})
import Editor from '@guolao/vue-monaco-editor'
import { NButton } from 'naive-ui'
Expand Down

0 comments on commit c75cfe9

Please sign in to comment.