improve(ui):优化用户端详情页返回方式
This commit is contained in:
1 parent
d1c8b40eca
commit
73db4465db
3 files changed
+98
-17
No files matched your search
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, onBeforeUnmount } from 'vue'
|
||||
import { ref, computed, onMounted, onBeforeUnmount, provide, watch } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useTenantAuthStore } from '@/stores/tenant-auth'
|
||||
import { useNotificationCount } from '@/composables/useNotificationCount'
|
||||
@@ -85,6 +85,42 @@ const pageTitle = computed(() => {
|
||||
return (leaf?.meta?.title as string) || navItems.value.find((i) => isActive(i.path))?.label || '仪表盘'
|
||||
})
|
||||
|
||||
// 返回按钮注册机制(使用 provide/inject)
|
||||
const backButtonConfig = ref<{
|
||||
show: boolean
|
||||
title: string
|
||||
handler: () => void
|
||||
} | null>(null)
|
||||
|
||||
// 提供给子页面的注册方法
|
||||
function registerBackButton(config: { title: string; handler: () => void }) {
|
||||
backButtonConfig.value = {
|
||||
show: true,
|
||||
title: config.title,
|
||||
handler: config.handler,
|
||||
}
|
||||
}
|
||||
|
||||
// 提供给子页面的取消注册方法
|
||||
function unregisterBackButton() {
|
||||
backButtonConfig.value = null
|
||||
}
|
||||
|
||||
// 通过 provide 暴露给子组件
|
||||
provide('registerBackButton', registerBackButton)
|
||||
provide('unregisterBackButton', unregisterBackButton)
|
||||
|
||||
// 监听路由变化,清空返回按钮配置
|
||||
watch(() => route.path, () => {
|
||||
backButtonConfig.value = null
|
||||
})
|
||||
|
||||
const showBackButton = computed(() => backButtonConfig.value?.show ?? false)
|
||||
const backButtonTitle = computed(() => backButtonConfig.value?.title ?? '返回')
|
||||
function handleBack() {
|
||||
backButtonConfig.value?.handler()
|
||||
}
|
||||
|
||||
function isActive(path: string): boolean {
|
||||
return activePath.value === path || activePath.value.startsWith(path + '/')
|
||||
}
|
||||
@@ -329,13 +365,33 @@ onBeforeUnmount(() => {
|
||||
<div class="glass flex h-16 items-center justify-between rounded-2xl border border-white/70 px-3 shadow-glass-sm md:px-5">
|
||||
<!-- Left: Mobile Menu + Title -->
|
||||
<div class="flex min-w-0 items-center gap-3">
|
||||
<!-- Mobile: 返回按钮或菜单按钮 -->
|
||||
<button
|
||||
v-if="showBackButton"
|
||||
@click="handleBack"
|
||||
class="btn-ghost btn-icon lg:hidden"
|
||||
:title="backButtonTitle"
|
||||
>
|
||||
<Icon name="chevronLeft" size="md" />
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
@click="toggleMobile"
|
||||
class="btn-ghost btn-icon lg:hidden"
|
||||
>
|
||||
<Icon name="menu" size="md" />
|
||||
</button>
|
||||
<div class="hidden min-w-0 lg:block">
|
||||
|
||||
<!-- Desktop: 返回按钮 + 标题 -->
|
||||
<div class="hidden min-w-0 lg:flex lg:items-center lg:gap-2">
|
||||
<button
|
||||
v-if="showBackButton"
|
||||
@click="handleBack"
|
||||
class="btn-ghost btn-icon flex-shrink-0 text-gray-500 hover:text-gray-700"
|
||||
:title="backButtonTitle"
|
||||
>
|
||||
<Icon name="chevronLeft" size="md" />
|
||||
</button>
|
||||
<h1 class="truncate text-base font-semibold text-slate-800">{{ pageTitle }}</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { formatNumber } from '@/utils/renderUtils'
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { ref, computed, onMounted, inject, onBeforeUnmount } from 'vue'
|
||||
import { NInput, NCheckbox } from 'naive-ui'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useTenantAuthStore } from '@/stores/tenant-auth'
|
||||
@@ -17,6 +17,10 @@ const route = useRoute()
|
||||
const authStore = useTenantAuthStore()
|
||||
const teamEnabled = computed(() => !!authStore.tenant?.team_enabled)
|
||||
|
||||
// 注入返回按钮注册方法
|
||||
const registerBackButton = inject<(config: { title: string; handler: () => void }) => void>('registerBackButton')
|
||||
const unregisterBackButton = inject<() => void>('unregisterBackButton')
|
||||
|
||||
const memberId = computed(() => Number(route.params.id))
|
||||
|
||||
interface MemberInfo {
|
||||
@@ -412,11 +416,15 @@ async function handleSaveModels() {
|
||||
}
|
||||
}
|
||||
|
||||
function goBack() {
|
||||
router.push('/tenant/members')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 注册返回按钮
|
||||
if (registerBackButton) {
|
||||
registerBackButton({
|
||||
title: '返回成员列表',
|
||||
handler: () => router.push('/tenant/members'),
|
||||
})
|
||||
}
|
||||
|
||||
fetchMemberDetail()
|
||||
fetchUsage()
|
||||
fetchApiKeyCount()
|
||||
@@ -424,20 +432,18 @@ onMounted(() => {
|
||||
fetchAllModels()
|
||||
fetchMemberModels()
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
// 取消注册返回按钮
|
||||
if (unregisterBackButton) {
|
||||
unregisterBackButton()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TeamLockedBanner v-if="!teamEnabled" />
|
||||
<div v-else class="space-y-8">
|
||||
<!-- Back navigation -->
|
||||
<button
|
||||
@click="goBack"
|
||||
class="btn btn-ghost btn-sm text-gray-500 hover:text-gray-700 -ml-2"
|
||||
>
|
||||
<Icon name="chevronLeft" size="sm" />
|
||||
返回成员列表
|
||||
</button>
|
||||
|
||||
<!-- Loading state -->
|
||||
<div v-if="loading" class="flex justify-center py-12">
|
||||
<div class="spinner h-8 w-8 border-primary-500"></div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted, h } from 'vue'
|
||||
import { ref, reactive, computed, onMounted, onBeforeUnmount, inject, h } from 'vue'
|
||||
import type { DataTableColumns } from 'naive-ui'
|
||||
import { NButton, NDropdown, NTag } from 'naive-ui'
|
||||
import { renderBadge, formatDate, formatTokens, formatMs, tableScrollX } from '@/utils/renderUtils'
|
||||
@@ -20,6 +20,10 @@ const route = useRoute()
|
||||
const router = useRouter()
|
||||
const projectId = computed(() => Number(route.params.id))
|
||||
|
||||
// 注入返回按钮注册方法
|
||||
const registerBackButton = inject<(config: { title: string; handler: () => void }) => void>('registerBackButton')
|
||||
const unregisterBackButton = inject<() => void>('unregisterBackButton')
|
||||
|
||||
// Project info
|
||||
interface Project {
|
||||
id: number
|
||||
@@ -116,9 +120,24 @@ async function openScopeModal(keyId: number, keyName: string) {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 注册返回按钮
|
||||
if (registerBackButton) {
|
||||
registerBackButton({
|
||||
title: '返回项目列表',
|
||||
handler: () => router.push('/tenant/projects'),
|
||||
})
|
||||
}
|
||||
|
||||
fetchProject()
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
// 取消注册返回按钮
|
||||
if (unregisterBackButton) {
|
||||
unregisterBackButton()
|
||||
}
|
||||
})
|
||||
|
||||
// Usage stats
|
||||
const usageStats = ref<any>(null)
|
||||
const usageLoading = ref(false)
|
||||
|
||||
Reference in new issue
Block a user