fix(admin-web): invalidate workspace cache after every AI-points-consuming call
Top-nav quota chip (会员到期 / 生成文章 / AI 点数) only refreshes when its query is invalidated. Several mutations and stream-based flows that debit points or article quota on the server were not invalidating it, so users had to refresh the page to see updated balances. - TemplateWizardView: invalidate `['workspace']` inside `endAssistTask()`, covering analyze / title / outline assist tasks in one place. - FreeCreateView: invalidate after `articlesApi.create` success. - GenerateTaskDrawer: add `['workspace']` to the instant-generate `Promise.all` alongside the existing `articles` / `instantTasks` keys. - KolPromptEditor: invalidate in the `finally` of both `runAiAssistStream` (generate) and `generateSelectionAiPreview` (optimize) so abort / error paths also refresh. - ArticleEditorCanvas: bring in `useQueryClient` and invalidate in the selection-optimize stream `finally`. Together with the existing invalidations in TemplateWizard.generate, ImitationGenerate, KolGenerate, and article-regenerate, every quota- debiting call site now feeds the cache refresh. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -57,6 +57,7 @@ import {
|
|||||||
} from '@milkdown/kit/prose/state'
|
} from '@milkdown/kit/prose/state'
|
||||||
import { Decoration, DecorationSet, type EditorView } from '@milkdown/kit/prose/view'
|
import { Decoration, DecorationSet, type EditorView } from '@milkdown/kit/prose/view'
|
||||||
import { callCommand, replaceAll } from '@milkdown/kit/utils'
|
import { callCommand, replaceAll } from '@milkdown/kit/utils'
|
||||||
|
import { useQueryClient } from '@tanstack/vue-query'
|
||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
// NOTE: import each common stylesheet explicitly instead of the aggregate
|
// NOTE: import each common stylesheet explicitly instead of the aggregate
|
||||||
// `theme/common/style.css`. The aggregate transitively `@import`s `latex.css`,
|
// `theme/common/style.css`. The aggregate transitively `@import`s `latex.css`,
|
||||||
@@ -121,6 +122,7 @@ const emit = defineEmits<{
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
const queryClient = useQueryClient()
|
||||||
const crepeRef = shallowRef<Crepe | null>(null)
|
const crepeRef = shallowRef<Crepe | null>(null)
|
||||||
const syncingExternalMarkdown = ref(false)
|
const syncingExternalMarkdown = ref(false)
|
||||||
const editorRootRef = ref<HTMLElement | null>(null)
|
const editorRootRef = ref<HTMLElement | null>(null)
|
||||||
@@ -1481,6 +1483,7 @@ async function generateAiOptimizePreview(): Promise<void> {
|
|||||||
if (aiOptimizeAbortController === controller) {
|
if (aiOptimizeAbortController === controller) {
|
||||||
aiOptimizeAbortController = null
|
aiOptimizeAbortController = null
|
||||||
}
|
}
|
||||||
|
void queryClient.invalidateQueries({ queryKey: ['workspace'] })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ const instantGenerateMutation = useMutation({
|
|||||||
await Promise.all([
|
await Promise.all([
|
||||||
queryClient.invalidateQueries({ queryKey: ['articles'] }),
|
queryClient.invalidateQueries({ queryKey: ['articles'] }),
|
||||||
queryClient.invalidateQueries({ queryKey: ['instantTasks'] }),
|
queryClient.invalidateQueries({ queryKey: ['instantTasks'] }),
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['workspace'] }),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
onError: (error) => message.error(formatError(error)),
|
onError: (error) => message.error(formatError(error)),
|
||||||
|
|||||||
@@ -275,6 +275,7 @@ async function runAiAssistStream(payload: KolAssistRequest) {
|
|||||||
if (aiAssistAbortController === controller) {
|
if (aiAssistAbortController === controller) {
|
||||||
aiAssistAbortController = null
|
aiAssistAbortController = null
|
||||||
}
|
}
|
||||||
|
void queryClient.invalidateQueries({ queryKey: ['workspace'] })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,6 +412,7 @@ async function generateSelectionAiPreview() {
|
|||||||
if (selectionAiAbortController === controller) {
|
if (selectionAiAbortController === controller) {
|
||||||
selectionAiAbortController = null
|
selectionAiAbortController = null
|
||||||
}
|
}
|
||||||
|
void queryClient.invalidateQueries({ queryKey: ['workspace'] })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ const deleteMutation = useMutation({
|
|||||||
const createMutation = useMutation({
|
const createMutation = useMutation({
|
||||||
mutationFn: () => articlesApi.create({}),
|
mutationFn: () => articlesApi.create({}),
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
|
void queryClient.invalidateQueries({ queryKey: ['workspace'] })
|
||||||
void router.push({ name: 'article-editor', params: { id: String(data.id) } })
|
void router.push({ name: 'article-editor', params: { id: String(data.id) } })
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
|
|||||||
@@ -839,6 +839,7 @@ function beginAssistTask(kind: 'analyze' | 'title' | 'outline'): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function endAssistTask(): void {
|
function endAssistTask(): void {
|
||||||
|
void queryClient.invalidateQueries({ queryKey: ['workspace'] })
|
||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
assistModalOpen.value = false
|
assistModalOpen.value = false
|
||||||
assistBusy.value = false
|
assistBusy.value = false
|
||||||
|
|||||||
Reference in New Issue
Block a user