From 4d6b02dada557b4186cdcef843cd3859aeeaac01 Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期四, 02 四月 2026 19:28:57 +0800
Subject: [PATCH] #
---
rsf-design/src/components/core/layouts/art-page-content/index.vue | 6
rsf-design/src/router/guards/beforeEach.js | 66 ++++++++-
rsf-design/src/components/core/layouts/art-chat-window/index.vue | 298 ++++++++++++++++++++++-------------------
rsf-design/src/locales/langs/en.json | 2
rsf-design/src/locales/langs/zh.json | 2
5 files changed, 223 insertions(+), 151 deletions(-)
diff --git a/rsf-design/src/components/core/layouts/art-chat-window/index.vue b/rsf-design/src/components/core/layouts/art-chat-window/index.vue
index 3d40c28..7749458 100644
--- a/rsf-design/src/components/core/layouts/art-chat-window/index.vue
+++ b/rsf-design/src/components/core/layouts/art-chat-window/index.vue
@@ -7,28 +7,163 @@
class="ai-chat-drawer"
>
<div class="flex h-full min-h-0 flex-col overflow-hidden bg-[var(--art-main-bg-color)]">
- <div class="flex items-center gap-4 border-b border-[var(--el-border-color-lighter)] bg-[var(--art-main-bg-color)] px-6 py-4">
- <div class="flex size-11 items-center justify-center rounded-3xl bg-[var(--el-color-primary-light-9)] text-[var(--el-color-primary)]">
- <ArtSvgIcon icon="ri:robot-2-line" class="text-[22px]" />
- </div>
- <div class="min-w-0 flex-1">
- <div class="flex flex-wrap items-center gap-2">
- <h3 class="text-base font-semibold text-[var(--art-gray-900)]">{{ $t('ai.drawer.title') }}</h3>
- <ElTag v-if="streaming" type="success" effect="light" round>{{ $t('ai.drawer.streaming') }}</ElTag>
+ <div class="border-b border-[var(--el-border-color-lighter)] bg-[var(--art-main-bg-color)] px-5 py-3">
+ <div class="flex items-center gap-3">
+ <div class="flex size-10 items-center justify-center rounded-3xl bg-[var(--el-color-primary-light-9)] text-[var(--el-color-primary)]">
+ <ArtSvgIcon icon="ri:robot-2-line" class="text-xl" />
</div>
- <p class="mt-1 truncate text-xs text-[var(--art-gray-500)]">
- {{ runtime?.promptName || runtime?.promptCode || DEFAULT_PROMPT_CODE }}
- </p>
+ <div class="min-w-0 flex-1">
+ <div class="flex flex-wrap items-center gap-2">
+ <h3 class="text-base font-semibold text-[var(--art-gray-900)]">{{ $t('ai.drawer.title') }}</h3>
+ <ElTag v-if="streaming" type="success" effect="light" round>{{ $t('ai.drawer.streaming') }}</ElTag>
+ </div>
+ <p class="mt-1 truncate text-xs text-[var(--art-gray-500)]">
+ {{ runtime?.promptName || runtime?.promptCode || DEFAULT_PROMPT_CODE }}
+ </p>
+ </div>
+ <ElButton plain :disabled="streaming" @click="startNewSession">
+ <ArtSvgIcon icon="ri:add-line" class="mr-1 text-sm" />
+ {{ $t('ai.drawer.newSession') }}
+ </ElButton>
+ <ArtIconButton icon="ri:close-line" @click="closeChat" />
</div>
- <ElButton plain :disabled="streaming" @click="startNewSession">
- <ArtSvgIcon icon="ri:add-line" class="mr-1 text-sm" />
- {{ $t('ai.drawer.newSession') }}
- </ElButton>
- <ArtIconButton icon="ri:close-line" @click="closeChat" />
+
+ <ElCollapseTransition>
+ <div
+ v-if="!runtimePreviewCollapsed"
+ class="mt-3 rounded-3xl bg-g-100/35 px-4 py-3 ring-1 ring-[var(--el-border-color-lighter)]"
+ >
+ <div class="flex flex-wrap items-start justify-between gap-3">
+ <div class="min-w-0 flex-1">
+ <div class="flex flex-wrap items-center gap-2">
+ <div class="text-sm font-semibold text-[var(--art-gray-900)]">{{ $t('ai.drawer.runtimeOverview') }}</div>
+ <div class="text-xs text-[var(--art-gray-500)]">{{ usageSummaryText }}</div>
+ </div>
+
+ <div class="mt-3 flex flex-wrap gap-2">
+ <div
+ v-for="item in runtimeMetricCards"
+ :key="item.label"
+ class="flex min-w-[150px] flex-1 items-center gap-2 rounded-2xl bg-[var(--art-main-bg-color)] px-3 py-2 ring-1 ring-[var(--el-border-color-extra-light)]"
+ >
+ <ArtSvgIcon :icon="item.icon" class="text-sm text-[var(--art-gray-500)]" />
+ <div class="min-w-0 flex-1">
+ <div class="text-[11px] text-[var(--art-gray-500)]">{{ item.label }}</div>
+ <div class="truncate text-sm font-medium text-[var(--art-gray-900)]">{{ item.value }}</div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="flex shrink-0 items-center gap-2">
+ <ElTag v-if="usage?.totalTokens != null" effect="plain" round>
+ {{ $t('ai.drawer.tokenMetric', {
+ prompt: usage?.promptTokens ?? 0,
+ completion: usage?.completionTokens ?? 0,
+ total: usage?.totalTokens ?? 0
+ }) }}
+ </ElTag>
+ <ElButton text @click="runtimePreviewCollapsed = true">
+ {{ $t('ai.drawer.runtimePreviewCollapse') }}
+ </ElButton>
+ </div>
+ </div>
+
+ <div class="mt-3 space-y-3 border-t border-[var(--el-border-color-extra-light)] pt-3">
+ <div class="flex flex-wrap items-center gap-3">
+ <ElSelect
+ v-if="selectableModelOptions.length"
+ v-model="selectedAiParamId"
+ :placeholder="$t('ai.drawer.modelSelectorLabel')"
+ :disabled="streaming || loadingRuntime || selectableModelOptions.length <= 1"
+ class="min-w-[280px]"
+ @change="handleModelChange"
+ >
+ <ElOption
+ v-for="item in selectableModelOptions"
+ :key="String(item.aiParamId)"
+ :label="formatModelOption(item)"
+ :value="item.aiParamId"
+ />
+ </ElSelect>
+
+ <div class="flex flex-wrap gap-2">
+ <ElButton
+ v-for="item in quickLinks"
+ :key="item.path"
+ plain
+ size="small"
+ @click="navigateTo(item.path)"
+ >
+ {{ item.label }}
+ </ElButton>
+ <ElButton plain size="small" :disabled="!sessionId || streaming" @click="handleRetainLatestRound">
+ {{ $t('ai.drawer.retainLatestRound') }}
+ </ElButton>
+ <ElButton plain size="small" :disabled="!sessionId || streaming" @click="handleClearMemory">
+ {{ $t('ai.drawer.clearMemory') }}
+ </ElButton>
+ </div>
+ </div>
+
+ <div class="flex flex-wrap gap-2">
+ <ElTag effect="plain" round>{{ $t('ai.drawer.requestMetric', { value: runtimeSummary.requestId }) }}</ElTag>
+ <ElTag effect="plain" round>{{ $t('ai.drawer.sessionMetric', { id: sessionId || '--' }) }}</ElTag>
+ <ElTag effect="plain" round>{{ $t('ai.drawer.recentMetric', { value: runtimeSummary.recentMessageCount }) }}</ElTag>
+ <ElTag :type="runtimeSummary.hasSummary ? 'success' : 'info'" effect="light" round>
+ {{ $t(runtimeSummary.hasSummary ? 'ai.drawer.hasSummary' : 'ai.drawer.noSummary') }}
+ </ElTag>
+ <ElTag :type="runtimeSummary.hasFacts ? 'success' : 'info'" effect="light" round>
+ {{ $t(runtimeSummary.hasFacts ? 'ai.drawer.hasFacts' : 'ai.drawer.noFacts') }}
+ </ElTag>
+ </div>
+
+ <ElAlert
+ v-if="runtime?.memorySummary"
+ type="info"
+ :closable="false"
+ :title="runtime.memorySummary"
+ />
+ <ElAlert
+ v-if="runtime?.memoryFacts"
+ type="success"
+ :closable="false"
+ :title="runtime.memoryFacts"
+ />
+ </div>
+ </div>
+ </ElCollapseTransition>
+
+ <ElCollapseTransition>
+ <div
+ v-if="runtimePreviewCollapsed"
+ class="mt-3 flex flex-wrap items-center justify-between gap-2 rounded-3xl bg-g-100/35 px-3 py-2 ring-1 ring-[var(--el-border-color-lighter)]"
+ >
+ <div class="flex min-w-0 flex-1 flex-wrap items-center gap-2">
+ <div class="text-sm font-semibold text-[var(--art-gray-900)]">{{ $t('ai.drawer.runtimeOverview') }}</div>
+ <div class="inline-flex max-w-[220px] items-center gap-1 rounded-full bg-[var(--art-main-bg-color)] px-2.5 py-1 text-xs text-[var(--art-gray-500)] ring-1 ring-[var(--el-border-color-extra-light)]">
+ <ArtSvgIcon icon="ri:cpu-line" class="text-[13px]" />
+ <span class="truncate">{{ runtimeSummary.model }}</span>
+ </div>
+ <div class="inline-flex max-w-[220px] items-center gap-1 rounded-full bg-[var(--art-main-bg-color)] px-2.5 py-1 text-xs text-[var(--art-gray-500)] ring-1 ring-[var(--el-border-color-extra-light)]">
+ <ArtSvgIcon icon="ri:magic-line" class="text-[13px]" />
+ <span class="truncate">{{ runtimeSummary.promptName }}</span>
+ </div>
+ <div class="inline-flex items-center gap-1 rounded-full bg-[var(--art-main-bg-color)] px-2.5 py-1 text-xs text-[var(--art-gray-500)] ring-1 ring-[var(--el-border-color-extra-light)]">
+ <ArtSvgIcon icon="ri:plug-2-line" class="text-[13px]" />
+ <span>{{ runtimeSummary.mountedMcpCount }}</span>
+ </div>
+ <div class="truncate text-xs text-[var(--art-gray-500)]">{{ usageSummaryText }}</div>
+ </div>
+ <ElButton text @click="runtimePreviewCollapsed = false">
+ {{ $t('ai.drawer.runtimePreviewExpand') }}
+ </ElButton>
+ </div>
+ </ElCollapseTransition>
</div>
<div class="min-h-0 flex-1 bg-g-100/35 ai-chat-body">
- <aside class="box-border flex min-h-0 flex-col gap-4 p-4 ai-chat-sidebar">
+ <aside class="box-border flex min-h-0 flex-col gap-3 p-3 ai-chat-sidebar">
<div class="rounded-3xl bg-[var(--art-main-bg-color)] p-4 shadow-[0_12px_36px_rgba(15,23,42,0.05)] ring-1 ring-[var(--el-border-color-lighter)]">
<div class="mb-3 flex items-center justify-between gap-3">
<div class="text-sm font-semibold text-[var(--art-gray-900)]">{{ $t('ai.drawer.sessionList') }}</div>
@@ -104,102 +239,7 @@
</div>
</aside>
- <section class="box-border flex min-h-0 flex-1 flex-col gap-4 p-4 pl-0">
- <div class="rounded-3xl bg-[var(--art-main-bg-color)] px-5 py-4 shadow-[0_12px_36px_rgba(15,23,42,0.05)] ring-1 ring-[var(--el-border-color-lighter)]">
- <div class="flex flex-wrap items-center justify-between gap-3">
- <div>
- <div class="text-sm font-semibold text-[var(--art-gray-900)]">{{ $t('ai.drawer.runtimeOverview') }}</div>
- <div class="mt-1 text-xs text-[var(--art-gray-500)]">
- {{ $t('ai.drawer.modelSelectorHint') }}
- </div>
- </div>
- <ElButton text @click="runtimePanelExpanded = !runtimePanelExpanded">
- {{ $t(runtimePanelExpanded ? 'ai.drawer.runtimeCollapse' : 'ai.drawer.runtimeExpand') }}
- </ElButton>
- </div>
-
- <ElCollapseTransition>
- <div v-show="runtimePanelExpanded" class="mt-4 space-y-4">
- <div class="grid gap-3 md:grid-cols-2 xl:grid-cols-4">
- <div
- v-for="item in runtimeMetricCards"
- :key="item.label"
- class="rounded-2xl bg-g-100/55 px-4 py-3 ring-1 ring-[var(--el-border-color-extra-light)]"
- >
- <div class="mb-2 flex items-center gap-2 text-xs text-[var(--art-gray-500)]">
- <ArtSvgIcon :icon="item.icon" class="text-sm" />
- <span>{{ item.label }}</span>
- </div>
- <div class="truncate text-sm font-semibold text-[var(--art-gray-900)]">
- {{ item.value }}
- </div>
- </div>
- </div>
-
- <div class="flex flex-wrap items-center gap-3">
- <ElSelect
- v-if="selectableModelOptions.length"
- v-model="selectedAiParamId"
- :placeholder="$t('ai.drawer.modelSelectorLabel')"
- :disabled="streaming || loadingRuntime || selectableModelOptions.length <= 1"
- class="min-w-[280px]"
- @change="handleModelChange"
- >
- <ElOption
- v-for="item in selectableModelOptions"
- :key="String(item.aiParamId)"
- :label="formatModelOption(item)"
- :value="item.aiParamId"
- />
- </ElSelect>
-
- <div class="flex flex-wrap gap-2">
- <ElButton
- v-for="item in quickLinks"
- :key="item.path"
- plain
- size="small"
- @click="navigateTo(item.path)"
- >
- {{ item.label }}
- </ElButton>
- <ElButton plain size="small" :disabled="!sessionId || streaming" @click="handleRetainLatestRound">
- {{ $t('ai.drawer.retainLatestRound') }}
- </ElButton>
- <ElButton plain size="small" :disabled="!sessionId || streaming" @click="handleClearMemory">
- {{ $t('ai.drawer.clearMemory') }}
- </ElButton>
- </div>
- </div>
-
- <div class="flex flex-wrap gap-2">
- <ElTag effect="plain" round>{{ $t('ai.drawer.requestMetric', { value: runtimeSummary.requestId }) }}</ElTag>
- <ElTag effect="plain" round>{{ $t('ai.drawer.sessionMetric', { id: sessionId || '--' }) }}</ElTag>
- <ElTag effect="plain" round>{{ $t('ai.drawer.recentMetric', { value: runtimeSummary.recentMessageCount }) }}</ElTag>
- <ElTag :type="runtimeSummary.hasSummary ? 'success' : 'info'" effect="light" round>
- {{ $t(runtimeSummary.hasSummary ? 'ai.drawer.hasSummary' : 'ai.drawer.noSummary') }}
- </ElTag>
- <ElTag :type="runtimeSummary.hasFacts ? 'success' : 'info'" effect="light" round>
- {{ $t(runtimeSummary.hasFacts ? 'ai.drawer.hasFacts' : 'ai.drawer.noFacts') }}
- </ElTag>
- </div>
-
- <ElAlert
- v-if="runtime?.memorySummary"
- type="info"
- :closable="false"
- :title="runtime.memorySummary"
- />
- <ElAlert
- v-if="runtime?.memoryFacts"
- type="success"
- :closable="false"
- :title="runtime.memoryFacts"
- />
- </div>
- </ElCollapseTransition>
- </div>
-
+ <section class="box-border flex min-h-0 flex-1 flex-col gap-3 p-3 pl-0">
<ElAlert
v-if="drawerError"
type="warning"
@@ -304,26 +344,8 @@
</button>
</div>
- <div class="flex min-h-0 flex-1 flex-col gap-4 ai-chat-main-column">
+ <div class="flex min-h-0 flex-1 flex-col gap-3 ai-chat-main-column">
<div class="flex min-h-0 flex-1 flex-col overflow-hidden rounded-3xl bg-[var(--art-main-bg-color)] shadow-[0_12px_36px_rgba(15,23,42,0.05)] ring-1 ring-[var(--el-border-color-lighter)]">
- <div class="flex flex-wrap items-center justify-between gap-3 border-b border-[var(--el-border-color-extra-light)] px-5 py-4">
- <div>
- <div class="text-sm font-semibold text-[var(--art-gray-900)]">{{ currentSessionTitle }}</div>
- <div class="mt-1 text-xs text-[var(--art-gray-500)]">
- {{ usageSummaryText }}
- </div>
- </div>
- <div class="flex flex-wrap gap-2">
- <ElTag v-if="usage?.totalTokens != null" effect="plain" round>
- {{ $t('ai.drawer.tokenMetric', {
- prompt: usage?.promptTokens ?? 0,
- completion: usage?.completionTokens ?? 0,
- total: usage?.totalTokens ?? 0
- }) }}
- </ElTag>
- </div>
- </div>
-
<ElScrollbar class="min-h-0 flex-1 bg-g-100/35 px-5 py-5">
<div class="space-y-5">
<div v-if="!messages.length" class="rounded-3xl border border-dashed border-[var(--el-border-color)] bg-slate-50/80 px-4 py-8 text-center text-sm text-[var(--art-gray-500)]">
@@ -489,7 +511,7 @@
const sessionKeyword = ref('')
const loadingRuntime = ref(false)
const streaming = ref(false)
- const runtimePanelExpanded = ref(false)
+ const runtimePreviewCollapsed = ref(true)
const tracePanelExpanded = ref(false)
const messagesBottomRef = ref(null)
const renameDialog = reactive({
@@ -583,7 +605,7 @@
watch(isDrawerVisible, async (visible) => {
if (visible) {
- runtimePanelExpanded.value = false
+ runtimePreviewCollapsed.value = true
tracePanelExpanded.value = false
await initializeDrawer()
scrollMessagesToBottom()
@@ -1050,16 +1072,16 @@
}
.ai-chat-sidebar {
- width: 320px;
+ width: 248px;
}
.ai-chat-workspace {
display: flex;
- gap: 16px;
+ gap: 12px;
}
.ai-chat-trace-column {
- width: 360px;
+ width: 312px;
flex-shrink: 0;
transition:
width 0.2s ease,
@@ -1067,7 +1089,7 @@
}
.ai-chat-trace-column--collapsed {
- width: 88px;
+ width: 72px;
}
.ai-chat-trace-collapsed-label {
diff --git a/rsf-design/src/components/core/layouts/art-page-content/index.vue b/rsf-design/src/components/core/layouts/art-page-content/index.vue
index b6c9e1a..c208db8 100644
--- a/rsf-design/src/components/core/layouts/art-page-content/index.vue
+++ b/rsf-design/src/components/core/layouts/art-page-content/index.vue
@@ -14,7 +14,7 @@
</div>
</div>
- <div v-if="routeRenderError" class="art-page-view art-route-state">
+ <div v-if="routeRenderError" :key="route.fullPath" class="art-page-view art-route-state">
<div class="art-route-state__panel">
<div class="art-route-state__title">{{ t('message.routeRenderFailedTitle') }}</div>
<div class="art-route-state__desc">{{ routeRenderError }}</div>
@@ -27,7 +27,7 @@
<RouterView v-else-if="isRefresh" v-slot="{ Component, route }">
<!-- 缂撳瓨璺敱鍔ㄧ敾 -->
<Transition :name="showTransitionMask ? '' : actualTransition" mode="out-in" appear>
- <div v-if="route.meta.keepAlive" class="art-page-view" :style="contentStyle">
+ <div v-if="route.meta.keepAlive" :key="route.path" class="art-page-view" :style="contentStyle">
<KeepAlive :max="10" :exclude="keepAliveExclude">
<component :is="Component" :key="route.path" />
</KeepAlive>
@@ -36,7 +36,7 @@
<!-- 闈炵紦瀛樿矾鐢卞姩鐢� -->
<Transition :name="showTransitionMask ? '' : actualTransition" mode="out-in" appear>
- <div v-if="!route.meta.keepAlive" class="art-page-view" :style="contentStyle">
+ <div v-if="!route.meta.keepAlive" :key="route.path" class="art-page-view" :style="contentStyle">
<component :is="Component" :key="route.path" />
</div>
</Transition>
diff --git a/rsf-design/src/locales/langs/en.json b/rsf-design/src/locales/langs/en.json
index caac110..0741f93 100644
--- a/rsf-design/src/locales/langs/en.json
+++ b/rsf-design/src/locales/langs/en.json
@@ -645,6 +645,8 @@
"runtimeOverview": "Runtime Overview",
"runtimeExpand": "Show Overview",
"runtimeCollapse": "Hide Overview",
+ "runtimePreviewExpand": "Show Runtime Preview",
+ "runtimePreviewCollapse": "Collapse Runtime Preview",
"loadingRuntime": "Loading AI runtime info...",
"emptyHint": "AI responses stream back through SSE here. You can also maintain parameters, prompts, and MCP mounts from the quick links above.",
"userRole": "You",
diff --git a/rsf-design/src/locales/langs/zh.json b/rsf-design/src/locales/langs/zh.json
index 3995d16..1a9a3ff 100644
--- a/rsf-design/src/locales/langs/zh.json
+++ b/rsf-design/src/locales/langs/zh.json
@@ -647,6 +647,8 @@
"runtimeOverview": "杩愯姒傝",
"runtimeExpand": "灞曞紑姒傝",
"runtimeCollapse": "鏀惰捣姒傝",
+ "runtimePreviewExpand": "灞曞紑杩愯棰勮",
+ "runtimePreviewCollapse": "鎶樺彔杩愯棰勮",
"loadingRuntime": "姝e湪鍔犺浇 AI 杩愯鏃朵俊鎭�...",
"emptyHint": "杩欓噷浼氶�氳繃 SSE 娴佸紡杩斿洖 AI 鍥炲銆備綘涔熷彲浠ュ厛鍘讳笂闈㈢殑蹇嵎鍏ュ彛缁存姢鍙傛暟銆丳rompt 鍜� MCP 鎸傝浇銆�",
"userRole": "浣�",
diff --git a/rsf-design/src/router/guards/beforeEach.js b/rsf-design/src/router/guards/beforeEach.js
index 1b797f0..96c6a21 100644
--- a/rsf-design/src/router/guards/beforeEach.js
+++ b/rsf-design/src/router/guards/beforeEach.js
@@ -50,6 +50,32 @@
pendingRouteLocation = null
return queuedRoute
}
+function isSameRouteLocation(firstRoute, secondRoute) {
+ if (!firstRoute || !secondRoute) {
+ return false
+ }
+ return (
+ firstRoute.path === secondRoute.path &&
+ JSON.stringify(firstRoute.query || {}) === JSON.stringify(secondRoute.query || {}) &&
+ (firstRoute.hash || '') === (secondRoute.hash || '')
+ )
+}
+function schedulePendingRouteNavigation(router, routeLocation) {
+ if (!routeLocation) {
+ return
+ }
+ setTimeout(() => {
+ const currentRoute = router.currentRoute?.value
+ if (isSameRouteLocation(currentRoute, routeLocation)) {
+ return
+ }
+ void router.push({
+ path: routeLocation.path,
+ query: routeLocation.query,
+ hash: routeLocation.hash
+ })
+ }, 0)
+}
function setupBeforeEachGuard(router) {
routeRegistry = new RouteRegistry(router)
router.beforeEach(async (to, from, next) => {
@@ -176,33 +202,53 @@
menuStore.addRemoveRouteFns(routeRegistry?.getRemoveRouteFns() || [])
IframeRouteManager.getInstance().save()
useWorktabStore().validateWorktabs(router)
- const targetLocation = consumePendingRoute() || createRouteLocation(to)
- if (isStaticRoute(targetLocation.path)) {
+ const initialTargetLocation = createRouteLocation(to)
+ const queuedTargetLocation = consumePendingRoute()
+ if (isStaticRoute(initialTargetLocation.path)) {
routeInitInProgress = false
- next(targetLocation)
+ next(initialTargetLocation)
+ if (queuedTargetLocation) {
+ schedulePendingRouteNavigation(router, queuedTargetLocation)
+ }
return
}
const { homePath } = useCommon()
- const { path: validatedPath, hasPermission } = RoutePermissionValidator.validatePath(
- targetLocation.path,
+ const initialValidation = RoutePermissionValidator.validatePath(
+ initialTargetLocation.path,
menuList,
homePath.value || '/'
)
+ const queuedValidation = queuedTargetLocation
+ ? RoutePermissionValidator.validatePath(
+ queuedTargetLocation.path,
+ menuList,
+ homePath.value || '/'
+ )
+ : null
routeInitInProgress = false
- if (!hasPermission) {
+ if (!initialValidation.hasPermission) {
closeLoading()
- console.warn(`[RouteGuard] 鐢ㄦ埛鏃犳潈闄愯闂矾寰�: ${targetLocation.path}锛屽凡璺宠浆鍒伴椤礰)
+ console.warn(`[RouteGuard] 鐢ㄦ埛鏃犳潈闄愯闂矾寰�: ${initialTargetLocation.path}锛屽凡璺宠浆鍒伴椤礰)
next({
- path: validatedPath,
+ path: initialValidation.path,
replace: true
})
} else {
next({
- ...targetLocation,
- path: validatedPath,
+ ...initialTargetLocation,
+ path: initialValidation.path,
replace: true
})
}
+ if (queuedValidation) {
+ if (!queuedValidation.hasPermission) {
+ console.warn(`[RouteGuard] 鐢ㄦ埛鏃犳潈闄愯闂矾寰�: ${queuedTargetLocation.path}锛屽凡璺宠浆鍒伴椤礰)
+ }
+ schedulePendingRouteNavigation(router, {
+ ...queuedTargetLocation,
+ path: queuedValidation.path
+ })
+ }
} catch (error) {
console.error('[RouteGuard] 鍔ㄦ�佽矾鐢辨敞鍐屽け璐�:', error)
closeLoading()
--
Gitblit v1.9.1