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 <noreply@anthropic.com>
This commit is contained in:
diguaandClaude Sonnet 4.6 committed 2026-06-15 23:11:06 +08:00
1 parent a89d6f7429
commit 2dba862c49
1 file changed
+13 -10
+13 -10
View File
@@ -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<WordFreqResponse>('/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<WordFreqResponse>('/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 () => {
</div>
</div>
<template v-if="canAnalyzeWithoutDictBlocking">
<template v-if="isDictListReady">
<div class="space-y-6">
<LoadingState v-if="isLoading && topWords.length === 0" :text="t('quotes.wordcloud.loading')" class="py-8" />