From 2dba862c49f95315f1948d911212d4fab0f74261 Mon Sep 17 00:00:00 2001 From: digua Date: Mon, 15 Jun 2026 23:11:06 +0800 Subject: [PATCH] fix(wordcloud): fix UX regressions for word cloud dictionary loading (#228) Switching to a different session left allWords/topicMiniWords/stats populated with the previous session's data. With the earlier fix that skips isLoading when allWords is non-empty, users could see and interact with stale words until the new request resolved. Extend the sessionId watcher to also clear all word cloud state so the loading indicator triggers correctly for cross-session navigation while still keeping old data visible for same-session filter refinements. Co-Authored-By: Claude Sonnet 4.6 --- .../analysis/quotes/WordcloudTab.vue | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/components/analysis/quotes/WordcloudTab.vue b/src/components/analysis/quotes/WordcloudTab.vue index a1f8caed..dde0c0ce 100644 --- a/src/components/analysis/quotes/WordcloudTab.vue +++ b/src/components/analysis/quotes/WordcloudTab.vue @@ -161,15 +161,14 @@ const dictOptions = computed(() => { const hasAnyDict = computed(() => { return dictList.value.some((d) => d.downloaded) }) -// 即使没有外部词典,内置 jieba 分词器也能正常工作,不应阻止分析 -const canAnalyzeWithoutDictBlocking = computed(() => dictListInitialized.value) +// 非中文语言无需词典即可分析;中文语言在词典列表初始化后可用内置分词器兜底 +const isDictListReady = computed(() => !requiresChineseDict.value || dictListInitialized.value) const undownloadedDicts = computed(() => { return dictList.value.filter((d) => !d.downloaded) }) async function refreshDictList() { - dictListInitialized.value = false try { dictList.value = await get('/nlp/dicts') // 繁体中文用户自动切换到 zh-TW(如已下载) @@ -277,7 +276,7 @@ async function loadPosTagDefinitions() { // 加载话题迷你词云数据(固定词性过滤) let topicMiniWordsRequestId = 0 async function loadTopicMiniWords() { - if (!props.sessionId || !canAnalyzeWithoutDictBlocking.value) return + if (!props.sessionId || !isDictListReady.value) return const requestId = ++topicMiniWordsRequestId try { const result = await analyticsPost('/nlp/word-frequency', { @@ -309,10 +308,10 @@ async function loadTopicMiniWords() { // 加载词频数据 let wordFrequencyRequestId = 0 async function loadWordFrequency() { - if (!props.sessionId || !canAnalyzeWithoutDictBlocking.value) return + if (!props.sessionId || !isDictListReady.value) return const requestId = ++wordFrequencyRequestId - isLoading.value = true + if (allWords.value.length === 0) isLoading.value = true try { const result = await analyticsPost('/nlp/word-frequency', { sessionId: props.sessionId, @@ -360,11 +359,15 @@ async function loadWordFrequency() { } } -// 切换会话时重置用户筛选 +// 切换会话时重置筛选状态并清空词云数据,避免展示上一个会话的陈旧内容 watch( () => props.sessionId, () => { selectedMemberId.value = null + allWords.value = [] + topicMiniWords.value = [] + stats.value = { totalMessages: 0, totalWords: 0, uniqueWords: 0 } + posTagStats.value = new Map() } ) @@ -378,7 +381,7 @@ watch( enableStopwords.value, selectedDictType.value, currentExcludeWords.value, - canAnalyzeWithoutDictBlocking.value, + isDictListReady.value, ], () => { loadWordFrequency() @@ -394,7 +397,7 @@ watch( selectedMemberId.value, selectedDictType.value, currentExcludeWords.value, - canAnalyzeWithoutDictBlocking.value, + isDictListReady.value, ], () => { loadTopicMiniWords() @@ -461,7 +464,7 @@ onMounted(async () => { -