优化: 前端体验批次(Knowledge持久化+流式缓存失效 + dfnodes节点注册 + delta 50ms合批 + MCP schema必填校验+bind_directory对齐)
This commit is contained in:
@@ -171,6 +171,7 @@ const {
|
||||
scheduleStreamParse,
|
||||
clearStreamingState,
|
||||
cancelPendingRaf,
|
||||
resetStreamCache,
|
||||
} = useStreamRenderer({
|
||||
saveSelection,
|
||||
restoreSelection,
|
||||
@@ -715,6 +716,8 @@ watch(() => store.state.activeConversationId, () => {
|
||||
} else {
|
||||
cancelPendingRaf()
|
||||
}
|
||||
// 切会话同步清流式块级 memo 缓存(_blockCache),防旧会话已缓存块被新会话命中。
|
||||
resetStreamCache()
|
||||
})
|
||||
|
||||
// 流式 rAF 清理:组件卸载时若仍有 pending rAF(streaming 中途切走/关窗),取消防泄漏。
|
||||
|
||||
@@ -207,6 +207,12 @@ export function useStreamRenderer(opts: UseStreamRendererOptions) {
|
||||
if (rafId !== null) { cancelAnimationFrame(rafId); rafId = null }
|
||||
}
|
||||
|
||||
/// 清空实例级块缓存(内容寻址 Map + LRU)。会话切换/开关变化时调用,
|
||||
/// 防旧会话已缓存块被新会话命中(跨会话内容错乱)。仅清缓存,不动 streamingBlocks。
|
||||
function resetStreamCache(): void {
|
||||
_blockCache.clear()
|
||||
}
|
||||
|
||||
return {
|
||||
mdReady,
|
||||
renderMd,
|
||||
@@ -216,5 +222,6 @@ export function useStreamRenderer(opts: UseStreamRendererOptions) {
|
||||
renderStreamingBlocks,
|
||||
clearStreamingState,
|
||||
cancelPendingRaf,
|
||||
resetStreamCache,
|
||||
}
|
||||
}
|
||||
|
||||
+7
-37
@@ -161,6 +161,7 @@ import {
|
||||
} from '@/stores/knowledge'
|
||||
import { useRendered } from '@/composables/useMarkdown'
|
||||
import { useToast } from '@/composables/useToast'
|
||||
import { usePersistedRef } from '@/composables/usePersistedRef'
|
||||
import { stripMd } from '@/utils/markdown'
|
||||
import KnowledgeDetail from '@/components/knowledge/KnowledgeDetail.vue'
|
||||
import type { KnowledgeDetailPayload, KnowledgeRecord } from '@/api/types'
|
||||
@@ -170,38 +171,10 @@ const store = useKnowledgeStore()
|
||||
// ⑤ 编辑/审核反馈:成功/失败明确提示(对齐 Settings.vue/Projects.vue useToast 模式)
|
||||
const { toast, showToast } = useToast()
|
||||
|
||||
// ④ topTab/activeKind/searchQuery 持久化 localStorage(跨刷新保留用户视图态)
|
||||
// 仅持久化视图态:不持久化详情选中(id 跨刷新可能已失效)。容错:解析失败/无效值回退默认。
|
||||
const LS_KEY = 'kn.view'
|
||||
function loadView(): { topTab: 'library' | 'inbox'; activeKind: string; searchQuery: string } {
|
||||
try {
|
||||
const raw = localStorage.getItem(LS_KEY)
|
||||
if (!raw) return { topTab: 'library', activeKind: 'all', searchQuery: '' }
|
||||
const v = JSON.parse(raw)
|
||||
return {
|
||||
topTab: v.topTab === 'inbox' ? 'inbox' : 'library',
|
||||
activeKind: typeof v.activeKind === 'string' ? v.activeKind : 'all',
|
||||
searchQuery: typeof v.searchQuery === 'string' ? v.searchQuery : '',
|
||||
}
|
||||
} catch {
|
||||
return { topTab: 'library', activeKind: 'all', searchQuery: '' }
|
||||
}
|
||||
}
|
||||
function saveView() {
|
||||
try {
|
||||
localStorage.setItem(LS_KEY, JSON.stringify({
|
||||
topTab: topTab.value,
|
||||
activeKind: activeKind.value,
|
||||
searchQuery: searchQuery.value,
|
||||
}))
|
||||
} catch {
|
||||
/* localStorage 不可用(隐私模式/配额)静默降级,视图态非关键 */
|
||||
}
|
||||
}
|
||||
const persisted = loadView()
|
||||
|
||||
// 顶层 Tab: library(知识库) | inbox(审核收件箱)
|
||||
const topTab = ref<'library' | 'inbox'>(persisted.topTab)
|
||||
// topTab/activeKind/searchQuery 持久化 localStorage(跨刷新保留用户视图态)
|
||||
// 仅持久化视图态:不持久化详情选中(id 跨刷新可能已失效)。usePersistedRef 无类型校验,
|
||||
// 解析失败/无效值回退 default,与 Tasks/Ideas 一致。
|
||||
const topTab = usePersistedRef<'library' | 'inbox'>('knowledge.topTab', 'library')
|
||||
|
||||
const categories = [
|
||||
{ key: 'all', icon: '📦' },
|
||||
@@ -211,8 +184,8 @@ const categories = [
|
||||
function catLabel(key: string): string {
|
||||
return key === 'all' ? t('knowledge.categoryAll') : kindText(key)
|
||||
}
|
||||
const activeKind = ref(persisted.activeKind)
|
||||
const searchQuery = ref(persisted.searchQuery)
|
||||
const activeKind = usePersistedRef('knowledge.activeKind', 'all')
|
||||
const searchQuery = usePersistedRef('knowledge.searchQuery', '')
|
||||
let searchTimer: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
function onSearchInput() {
|
||||
@@ -246,9 +219,6 @@ function switchTopTab(tab: 'library' | 'inbox') {
|
||||
}
|
||||
}
|
||||
|
||||
// ④ 视图态(topTab/activeKind/searchQuery)持久化:任一变化即写 localStorage
|
||||
watch([topTab, activeKind, searchQuery], saveView)
|
||||
|
||||
// 关闭错误条
|
||||
function clearError() {
|
||||
store.clearError()
|
||||
|
||||
Reference in New Issue
Block a user