feat(kol): return to source page after generation and poll while busy

- Add a ?source=workspace|templates query param when opening the
  generate page so the back button and the post-submit redirect return
  to the originating page; invalidate articles + workspace caches on
  success so the new article shows up immediately.
- Poll recent articles every 10s in WorkspaceView and TemplatesView
  while any article is in queued/pending/generating/running, and stop
  the timer once nothing is active.
- Mark the new article as generating inside the generation Submit
  transaction so the client sees the right status as soon as the task
  is queued.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-18 17:17:17 +08:00
parent fe4a4ffeaa
commit 6e77f72c53
5 changed files with 105 additions and 13 deletions
+12 -4
View File
@@ -189,6 +189,10 @@ const displayedArticleTotal = computed(() =>
let articlePollingTimer: number | null = null;
function hasActiveGenerationStatus(status?: string | null): boolean {
return status === "queued" || status === "pending" || status === "generating" || status === "running";
}
const deleteMutation = useMutation({
mutationFn: (articleId: number) => articlesApi.remove(articleId),
onSuccess: async () => {
@@ -324,7 +328,11 @@ function startTemplate(template: TemplateListItem): void {
function openRefinedTemplate(card: KolWorkspaceCard): void {
pickerOpen.value = false;
pickerMode.value = null;
void router.push({ name: "kol-generate", params: { subscriptionPromptId: String(card.subscription_prompt_id) } });
void router.push({
name: "kol-generate",
params: { subscriptionPromptId: String(card.subscription_prompt_id) },
query: { source: "templates" },
});
}
async function openEditor(article: ArticleListItem): Promise<void> {
@@ -362,7 +370,7 @@ watch(
() => displayedArticles.value,
(items: ArticleListItem[]) => {
const hasGeneratingArticles = items.some((item: ArticleListItem) =>
item.generate_status === "generating" || item.generate_status === "running",
hasActiveGenerationStatus(item.generate_status),
);
if (hasGeneratingArticles) {
@@ -390,8 +398,8 @@ function startArticlePolling(): void {
}
articlePollingTimer = window.setInterval(() => {
void articleListQuery.refetch();
}, 3000);
void Promise.all([articleListQuery.refetch(), recentArticlesQuery.refetch()]);
}, 10000);
}
function stopArticlePolling(): void {