fix(tasks): 任务取消 - 禁止取消已开始的生成任务

This commit is contained in:
ddCat
2026-08-21 17:06:05 +08:00
parent 1af765d52a
commit 7418ddfa9c
7 changed files with 88 additions and 41 deletions

View File

@@ -20,7 +20,7 @@ import { listProjects, type ProjectSummary } from "@/services/api/projects";
import { TaskGridCard } from "./task-grid-card";
import { TaskGroupHeader, type TaskGroup } from "./task-group-header";
import { TaskListRow } from "./task-list-row";
import { formatModelName, getTaskCanvasContext, isTaskFailed, providerCancelStatusLabel, taskMediaKind } from "./task-shared";
import { formatModelName, getTaskCanvasContext, isTaskCancellable, isTaskFailed, providerCancelStatusLabel, taskMediaKind } from "./task-shared";
import { TaskStatusFilterBar, type TaskStatusFilter } from "./task-status-filter";
type TaskKindFilter = "all" | "text" | "image" | "video";
@@ -292,6 +292,10 @@ export default function TasksPage() {
const runAction = async (id: string, action: "retry" | "cancel") => {
const currentTask = tasksRef.current.find((task) => task.id === id);
if (action === "cancel" && currentTask && !isTaskCancellable(currentTask)) {
message.warning("任务已开始生成,无法取消");
return;
}
if (action === "retry" && currentTask && isGenerationTaskSubmissionUncertain(currentTask)) {
message.warning("提交结果尚未确认,不能自动重试;请先核对官方状态,避免重复生成。");
return;
@@ -551,7 +555,7 @@ export default function TasksPage() {
更新官方状态
</Button>
) : null}
{detailTask.provider === "dreamina-cli" && (detailTask.status === "queued" || detailTask.status === "running") ? (
{detailTask.provider === "dreamina-cli" && isTaskCancellable(detailTask) ? (
<Button danger loading={actingId === detailTask.id} onClick={() => void runAction(detailTask.id, "cancel")}>
{localDreaminaCancellationCopy(detailTask)?.action || "取消任务"}
</Button>

View File

@@ -5,10 +5,11 @@ import { MediaPreview } from "@/components/media-preview";
import { CONTENT_MODERATION_ERROR_CODE, isContentModerationError } from "@/lib/generation-error";
import { statusLabel } from "@/lib/generation-task-display";
import type { GenerationTask } from "@/services/api/task-center";
import { isTaskFailed, statusDotClassName, TaskDate } from "./task-shared";
import { isTaskCancellable, isTaskFailed, statusDotClassName, TaskDate } from "./task-shared";
export function TaskGridCard({ task, actingId, onOpen, onRetry, onCancel }: { task: GenerationTask; actingId: string; onOpen: () => void; onRetry: () => void; onCancel: () => void }) {
const isActive = task.status === "queued" || task.status === "running";
const isCancellable = isTaskCancellable(task);
const isFailed = isTaskFailed(task);
const isVideo = task.previewKind === "video";
const fallbackVideo = task.type.includes("video");
@@ -38,7 +39,7 @@ export function TaskGridCard({ task, actingId, onOpen, onRetry, onCancel }: { ta
/>
</Tooltip>
) : null}
{isActive ? (
{isCancellable ? (
<Tooltip title="取消任务">
<Button type="text" size="small" danger icon={<X className="size-3.5" />} aria-label="取消任务" loading={actingId === task.id} onClick={onCancel} />
</Tooltip>

View File

@@ -7,7 +7,7 @@ import { CONTENT_MODERATION_ERROR_CODE, generationErrorMessage, isContentModerat
import { formatTaskKind, statusLabel } from "@/lib/generation-task-display";
import type { GenerationTask } from "@/services/api/task-center";
import type { AiConfig } from "@/stores/use-config-store";
import { formatModelName, getTaskCanvasContext, isTaskFailed, statusDotClassName, taskAttentionReason, TaskBilling, TaskDate } from "./task-shared";
import { formatModelName, getTaskCanvasContext, isTaskCancellable, isTaskFailed, statusDotClassName, taskAttentionReason, TaskBilling, TaskDate } from "./task-shared";
export function TaskListRow({
task,
@@ -34,6 +34,7 @@ export function TaskListRow({
}) {
const context = getTaskCanvasContext(task, canvasById, projectNameById);
const isActive = task.status === "queued" || task.status === "running";
const isCancellable = isTaskCancellable(task);
const isFailed = isTaskFailed(task);
return (
<article className={`task-record-row group${isFailed ? " is-attention" : ""}`}>
@@ -94,7 +95,7 @@ export function TaskListRow({
/>
</Tooltip>
) : null}
{isActive ? (
{isCancellable ? (
<Tooltip title="取消任务">
<Button type="text" size="small" danger icon={<X className="size-3.5" />} aria-label="取消任务" loading={actingId === task.id} onClick={onCancel} />
</Tooltip>

View File

@@ -17,6 +17,10 @@ export function isTaskFailed(task: GenerationTask) {
return task.status === "failed" || task.status === "cancelled";
}
export function isTaskCancellable(task: GenerationTask) {
return task.status === "queued";
}
export function taskAttentionReason(task: GenerationTask) {
if (task.status === "cancelled") return providerCancelStatusLabel(task);
if (task.errorCode === CONTENT_MODERATION_ERROR_CODE || isContentModerationError(task.error)) return "内容审核未通过,请修改输入后新建任务";