diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/patroldelete/model/dto/PatrolDeleteCreateTaskRequest.java b/backend-java/src/main/java/com/nanri/aiimage/modules/patroldelete/model/dto/PatrolDeleteCreateTaskRequest.java index 94a67dd4..71f455ce 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/patroldelete/model/dto/PatrolDeleteCreateTaskRequest.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/patroldelete/model/dto/PatrolDeleteCreateTaskRequest.java @@ -23,4 +23,10 @@ public class PatrolDeleteCreateTaskRequest { @NotEmpty @Schema(description = "待创建的店铺任务列表,通常由已匹配成功的店铺组成", requiredMode = Schema.RequiredMode.REQUIRED) private List items = new ArrayList<>(); + + @NotNull + @NotEmpty + @JsonProperty("delete_conditions") + @Schema(description = "删除条件(如:定价问题/需要批准/缺少报价…),为空时任务无可执行内容", requiredMode = Schema.RequiredMode.REQUIRED) + private List deleteConditions = new ArrayList<>(); } diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/patroldelete/service/PatrolDeleteTaskService.java b/backend-java/src/main/java/com/nanri/aiimage/modules/patroldelete/service/PatrolDeleteTaskService.java index 97179cec..5713d699 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/patroldelete/service/PatrolDeleteTaskService.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/patroldelete/service/PatrolDeleteTaskService.java @@ -280,6 +280,11 @@ public class PatrolDeleteTaskService { if (request.getItems() == null || request.getItems().isEmpty()) { throw new BusinessException("items 不能为空"); } + // 删除条件为空时任务没有可执行的判定规则(Python 端会无事可做、一直停在执行中), + // 必须在此拦截;前端亦在创建前拦截,此处为服务端兜底(直调 API/旧客户端场景) + if (request.getDeleteConditions() == null || request.getDeleteConditions().isEmpty()) { + throw new BusinessException("删除条件不能为空,请先选择删除条件"); + } List uniqueItems = dedupeItems(request.getItems()); if (uniqueItems.isEmpty()) { diff --git a/frontend-vue/src/pages/brand/components/BrandPatrolDeleteTab.vue b/frontend-vue/src/pages/brand/components/BrandPatrolDeleteTab.vue index a0895687..6728ca94 100644 --- a/frontend-vue/src/pages/brand/components/BrandPatrolDeleteTab.vue +++ b/frontend-vue/src/pages/brand/components/BrandPatrolDeleteTab.vue @@ -1062,8 +1062,14 @@ async function processQueue() { ElMessage.warning("请先匹配可用店铺"); return; } + if (!selectedDeleteConditions().length) { + // 删除条件为空时任务没有可执行的判定规则,必须在创建任务前拦截, + // 否则 Java 已创建(RUNNING)而 Python 端无事可做,任务会一直停在执行中 + ElMessage.warning("请先选择删除条件"); + return; + } const created = await withTransientRetry( - () => createPatrolDeleteTask(runnable.map(buildTaskItem)), + () => createPatrolDeleteTask(runnable.map(buildTaskItem), selectedDeleteConditions()), (attempt, maxAttempts) => { queuePushResult.value = `服务暂时不可用,正在重试创建任务(${attempt}/${maxAttempts})...`; }, diff --git a/frontend-vue/src/shared/api/types/modules/withdraw.ts b/frontend-vue/src/shared/api/types/modules/withdraw.ts index 334c4c4b..5a85382e 100644 --- a/frontend-vue/src/shared/api/types/modules/withdraw.ts +++ b/frontend-vue/src/shared/api/types/modules/withdraw.ts @@ -449,14 +449,19 @@ export function getPatrolDeleteTaskProgressBatch(taskIds: number[]) { ); } -export function createPatrolDeleteTask(items: PatrolDeleteTaskItem[]) { +export function createPatrolDeleteTask( + items: PatrolDeleteTaskItem[], + deleteConditions: unknown[] = [], +) { return unwrapJavaResponse( post< JavaApiResponse, - { user_id: number; items: PatrolDeleteTaskItem[] } + { user_id: number; items: PatrolDeleteTaskItem[]; delete_conditions: unknown[] } >(`${JAVA_API_PREFIX}/patrol-delete/tasks`, { user_id: getCurrentUserId(), items, + // 服务端校验删除条件非空(创建即 RUNNING,空条件的任务 Python 端无内容可执行) + delete_conditions: deleteConditions, }), ); }