mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-13 19:23:42 +08:00
fix(wiki): open failure records in owning workspace (#614)
This commit is contained in:
parent
709218e2ac
commit
2372827762
44
mateclaw-ui/src/views/Wiki/__tests__/failureOpen.test.ts
Normal file
44
mateclaw-ui/src/views/Wiki/__tests__/failureOpen.test.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { openWikiFailureItem } from '../utils/failureOpen'
|
||||
|
||||
describe('openWikiFailureItem', () => {
|
||||
it('switches to the owning workspace before opening a cross-workspace KB', async () => {
|
||||
const calls: string[] = []
|
||||
const workspaceStore = {
|
||||
currentWorkspaceId: 'ws-a',
|
||||
switchWorkspace: vi.fn(async (id: string) => {
|
||||
calls.push(`switch:${id}`)
|
||||
}),
|
||||
}
|
||||
const wikiStore = {
|
||||
selectKB: vi.fn(async (id: string, mode: 'browse' | 'manage') => {
|
||||
calls.push(`select:${id}:${mode}`)
|
||||
}),
|
||||
}
|
||||
|
||||
await openWikiFailureItem(
|
||||
{ kbId: 'kb-2', workspaceId: 'ws-b' },
|
||||
{ workspaceStore, wikiStore },
|
||||
)
|
||||
|
||||
expect(calls).toEqual(['switch:ws-b', 'select:kb-2:browse'])
|
||||
})
|
||||
|
||||
it('opens directly when the failure item belongs to the active workspace', async () => {
|
||||
const workspaceStore = {
|
||||
currentWorkspaceId: 'ws-a',
|
||||
switchWorkspace: vi.fn(),
|
||||
}
|
||||
const wikiStore = {
|
||||
selectKB: vi.fn(async () => {}),
|
||||
}
|
||||
|
||||
await openWikiFailureItem(
|
||||
{ kbId: 'kb-1', workspaceId: 'ws-a' },
|
||||
{ workspaceStore, wikiStore },
|
||||
)
|
||||
|
||||
expect(workspaceStore.switchWorkspace).not.toHaveBeenCalled()
|
||||
expect(wikiStore.selectKB).toHaveBeenCalledWith('kb-1', 'browse')
|
||||
})
|
||||
})
|
||||
@ -16,7 +16,7 @@
|
||||
</button>
|
||||
|
||||
<div v-show="!collapsed" class="fc-body">
|
||||
<div v-for="it in items" :key="it.rawId" class="fc-row" @click="$emit('open', it.kbId)">
|
||||
<div v-for="it in items" :key="it.rawId" class="fc-row" @click="$emit('open', it)">
|
||||
<span class="fc-badge" :class="rowKind(it)">{{ t(`wiki.status.${it.processingStatus}`) }}</span>
|
||||
<div class="fc-main">
|
||||
<div class="fc-line1">
|
||||
@ -25,7 +25,7 @@
|
||||
</div>
|
||||
<div class="fc-msg" :title="it.errorMessage || it.warningMessage || ''">{{ friendly(it) }}</div>
|
||||
</div>
|
||||
<button class="fc-open" @click.stop="$emit('open', it.kbId)">{{ t('wiki.failureCenter.open') }}</button>
|
||||
<button class="fc-open" @click.stop="$emit('open', it)">{{ t('wiki.failureCenter.open') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@ -36,7 +36,7 @@ import { ref, onMounted } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { wikiApi, type WikiFailureItem } from '@/api/index'
|
||||
|
||||
defineEmits<{ (e: 'open', kbId: string): void }>()
|
||||
defineEmits<{ (e: 'open', item: WikiFailureItem): void }>()
|
||||
|
||||
const { t } = useI18n()
|
||||
const items = ref<WikiFailureItem[]>([])
|
||||
|
||||
@ -48,18 +48,21 @@ import { ref, reactive, watch, onMounted, computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useWikiStore, type WikiKB } from '@/stores/useWikiStore'
|
||||
import { wikiApi } from '@/api/index'
|
||||
import { useWorkspaceStore } from '@/stores/useWorkspaceStore'
|
||||
import { wikiApi, type WikiFailureItem } from '@/api/index'
|
||||
import { mcConfirm } from '@/components/common/useConfirm'
|
||||
import { mcToast } from '@/composables/useMcToast'
|
||||
import WikiLibrary from './components/WikiLibrary.vue'
|
||||
import WikiWorkspace from './components/WikiWorkspace.vue'
|
||||
import WikiFailureCenter from './components/WikiFailureCenter.vue'
|
||||
import { openWikiFailureItem } from './utils/failureOpen'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const { t } = useI18n()
|
||||
const store = useWikiStore()
|
||||
const workspaceStore = useWorkspaceStore()
|
||||
|
||||
// The cross-KB failure center spans every workspace, so it is admin-only —
|
||||
// mirrors the gate on the backing endpoint.
|
||||
@ -95,10 +98,8 @@ async function enterKB(id: number) {
|
||||
await store.selectKB(id, 'browse')
|
||||
}
|
||||
|
||||
// The failure center emits a Snowflake kbId as a string — keep it a string end
|
||||
// to end (snowflake-precision-ok) and let the store cast satisfy its signature.
|
||||
async function openFromFailureCenter(kbId: string) {
|
||||
await store.selectKB(kbId as unknown as number, 'browse')
|
||||
async function openFromFailureCenter(item: WikiFailureItem) {
|
||||
await openWikiFailureItem(item, { workspaceStore, wikiStore: store })
|
||||
}
|
||||
|
||||
async function enterKBManage(id: number) {
|
||||
|
||||
27
mateclaw-ui/src/views/Wiki/utils/failureOpen.ts
Normal file
27
mateclaw-ui/src/views/Wiki/utils/failureOpen.ts
Normal file
@ -0,0 +1,27 @@
|
||||
export interface WikiFailureOpenItem {
|
||||
kbId: string
|
||||
workspaceId?: string | null
|
||||
}
|
||||
|
||||
export interface WikiFailureOpenDeps {
|
||||
workspaceStore: {
|
||||
currentWorkspaceId: string | null
|
||||
switchWorkspace: (id: string) => Promise<void> | void
|
||||
}
|
||||
wikiStore: {
|
||||
// The wiki store is still typed as number in places, but Snowflake KB IDs
|
||||
// are passed as strings at runtime to avoid precision loss.
|
||||
selectKB: (id: any, mode: 'browse' | 'manage') => Promise<void> | void
|
||||
}
|
||||
}
|
||||
|
||||
export async function openWikiFailureItem(
|
||||
item: WikiFailureOpenItem,
|
||||
deps: WikiFailureOpenDeps,
|
||||
) {
|
||||
const targetWorkspaceId = item.workspaceId || null
|
||||
if (targetWorkspaceId && deps.workspaceStore.currentWorkspaceId !== targetWorkspaceId) {
|
||||
await deps.workspaceStore.switchWorkspace(targetWorkspaceId)
|
||||
}
|
||||
await deps.wikiStore.selectKB(item.kbId, 'browse')
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user