fix(bot): resolve tab component cache invalidation issue

This commit is contained in:
Quicy
2026-03-04 16:33:23 +08:00
committed by 晨苒
parent 0a2a17ecc8
commit d8cc0f37b4
5 changed files with 58 additions and 65 deletions
@@ -610,7 +610,7 @@
<!-- Export dialog -->
<Dialog v-model:open="exportDialogOpen">
<DialogContent class="sm:max-w-lg w-[calc(100vw-2rem)] max-w-[calc(100vw-2rem)] sm:w-auto">
<DialogContent>
<DialogHeader>
<DialogTitle>{{ $t('common.export') }} mcpServers</DialogTitle>
</DialogHeader>
+40 -56
View File
@@ -111,9 +111,9 @@
<Toggle
:class="`py-4 border border-transparent ${activeTab === tab.value ? 'border-inherit' : ''}`"
:model-value="isActive(tab.value as string).value"
@update:model-value="(isSelect:boolean) => {
@update:model-value="(isSelect: boolean) => {
if (isSelect) {
activeTab=tab.value
activeTab = tab.value
}
}"
>
@@ -127,36 +127,14 @@
<template #sidebar-footer />
<template #detail>
<template v-if="activeTab === 'files'">
<div class="h-full">
<KeepAlive>
<BotFiles
:bot-id="botId"
:bot-type="bot?.type"
/>
</KeepAlive>
</div>
</template>
<template v-else-if="activeTab === 'mcp'">
<div class="h-full relative">
<KeepAlive>
<BotMcp
:bot-id="botId"
:bot-type="bot?.type"
/>
</KeepAlive>
</div>
</template>
<ScrollArea
v-else
class="max-h-full h-full"
>
<section class="p-4">
<KeepAlive>
<component
:is="activeComponent?.component"
:bot-id="botId"
:bot-type="bot?.type"
v-bind="activeComponent?.params"
/>
</KeepAlive>
</section>
@@ -241,7 +219,7 @@ import {
SidebarMenuItem,
Toggle
} from '@memoh/ui'
import { computed, ref, watch, onMounted } from 'vue'
import { computed, ref, watch, onMounted, toValue } from 'vue'
import { useRoute } from 'vue-router'
import { toast } from 'vue-sonner'
import { useI18n } from 'vue-i18n'
@@ -276,7 +254,6 @@ import { useAvatarInitials } from '@/composables/useAvatarInitials'
import { useSyncedQueryParam } from '@/composables/useSyncedQueryParam'
import { useBotStatusMeta } from '@/composables/useBotStatusMeta'
import MasterDetailSidebarLayout from '@/components/master-detail-sidebar-layout/index.vue'
type BotCheck = BotsBotCheck
type BotContainerInfo = HandlersGetContainerResponse
type BotContainerSnapshot = HandlersListSnapshotsResponse extends { snapshots?: (infer T)[] } ? T : never
@@ -285,35 +262,6 @@ const route = useRoute()
const { t } = useI18n()
const botId = computed(() => route.params.botId as string)
const tabList = [
{ value: 'overview', label: 'bots.tabs.overview',component: BotOverview },
{ value: 'memory', label: 'bots.tabs.memory',component:BotMemory },
{ value: 'channels', label: 'bots.tabs.channels', component: BotChannels },
{ value: 'email', label: 'bots.tabs.email', component: BotEmail },
{ value: 'container', label: 'bots.tabs.container', component: BotContainer },
{ value: 'files', label: 'bots.tabs.files', component: BotFiles },
{ value: 'mcp', label: 'bots.tabs.mcp' ,component: BotMcp },
{ value: 'subagents', label: 'bots.tabs.subagents',component: BotSubagents },
{ value: 'heartbeat', label: 'bots.tabs.heartbeat',component: BotHeartbeat },
{ value: 'schedule', label: 'bots.tabs.schedule', component: BotSchedule },
{ value: 'history', label: 'bots.tabs.history',component: BotHistory },
{ value: 'skills', label: 'bots.tabs.skills',component: BotSkills },
{ value: 'settings', label: 'bots.tabs.settings',component: BotSettings }
]
const isActive = (name: string) => computed(() => {
return activeTab.value===name
})
const activeComponent = computed(() => {
return tabList.find(tab=>tab.value===activeTab.value)
})
const capabilitiesStore = useCapabilitiesStore()
onMounted(() => {
void capabilitiesStore.load()
})
const { data: bot } = useQuery({
key: () => ['bot', botId.value],
query: async () => {
@@ -322,6 +270,42 @@ const { data: bot } = useQuery({
},
enabled: () => !!botId.value,
})
const tabList = computed(() => {
const bot_id = toValue(botId)
return [
{
value: 'overview', label: 'bots.tabs.overview', component: BotOverview, params: {}
},
{ value: 'memory', label: 'bots.tabs.memory', component: BotMemory, params: { 'bot-id': bot_id } },
{ value: 'channels', label: 'bots.tabs.channels', component: BotChannels, params: { 'bot-id': bot_id } },
{ value: 'email', label: 'bots.tabs.email', component: BotEmail, params: { 'bot-id': bot_id } },
{ value: 'container', label: 'bots.tabs.container', component: BotContainer, params: {} },
{ value: 'files', label: 'bots.tabs.files', component: BotFiles, params: { 'bot-id': bot_id, 'bot-type': bot.value?.type } },
{ value: 'mcp', label: 'bots.tabs.mcp', component: BotMcp, params: { 'bot-id': bot_id } },
{ value: 'subagents', label: 'bots.tabs.subagents', component: BotSubagents, params: { 'bot-id': bot_id } },
{ value: 'heartbeat', label: 'bots.tabs.heartbeat', component: BotHeartbeat, params: { 'bot-id': bot_id } },
{ value: 'schedule', label: 'bots.tabs.schedule', component: BotSchedule, params: { 'bot-id': bot_id } },
{ value: 'history', label: 'bots.tabs.history', component: BotHistory, params: { 'bot-id': bot_id } },
{ value: 'skills', label: 'bots.tabs.skills', component: BotSkills, params: { 'bot-id': bot_id } },
{ value: 'settings', label: 'bots.tabs.settings', component: BotSettings, params: { 'bot-id': bot_id, 'bot-type': bot.value?.type } }
]
})
const isActive = (name: string) => computed(() => {
return activeTab.value === name
})
const activeComponent = computed(() => {
return tabList.value.find(tab => tab.value === activeTab.value)
})
const capabilitiesStore = useCapabilitiesStore()
onMounted(() => {
void capabilitiesStore.load()
})
const queryCache = useQueryCache()
const { mutateAsync: updateBot, isLoading: updateBotLoading } = useMutation({
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { computed, ref, provide, watch, reactive } from 'vue'
import { useQuery, useQueryCache } from '@pinia/colada'
import { useQuery} from '@pinia/colada'
import {
Button,
ScrollArea,
@@ -29,8 +29,6 @@ const { data: providerData } = useQuery({
return data
},
})
const queryCache = useQueryCache()
const curProvider = ref<EmailProviderResponse>()
provide('curEmailProvider', curProvider)
@@ -3,7 +3,7 @@
<DialogTrigger as-child>
<Button
variant="outline"
class="w-full"
class="w-full mb-4 text-muted-foreground"
>
<FontAwesomeIcon
:icon="['fas', 'plus']"
@@ -14,6 +14,7 @@ import {
EmptyHeader,
EmptyMedia,
EmptyTitle,
Button
} from '@memoh/ui'
import { getMemoryProviders } from '@memoh/sdk'
import type { MemoryprovidersGetResponse } from '@memoh/sdk'
@@ -129,7 +130,17 @@ const openStatus = reactive({ addOpen: false })
<EmptyTitle>{{ $t('memoryProvider.emptyTitle') }}</EmptyTitle>
<EmptyDescription>{{ $t('memoryProvider.emptyDescription') }}</EmptyDescription>
<EmptyContent>
<AddMemoryProvider v-model:open="openStatus.addOpen" />
<Button
variant="outline"
class="w-full"
@click="openStatus.addOpen=true"
>
<FontAwesomeIcon
:icon="['fas', 'plus']"
class="mr-2"
/>
{{ $t('memoryProvider.add') }}
</Button>
</EmptyContent>
</Empty>
</template>