新增 shared/dispatch-guard.ts(纯 TS 校验,可单测)与 dispatch-guard-ui.ts
(ElMessageBox 弹窗层),在数据流的三个位置设闸:
- 选文件:空选择、非 xlsx/xls/csv、空路径直接拦;重复文件弹确认
- 解析结果:taskId 非法、totalRows 为 0、整批行被丢弃、需要分组却无分组直接拦;
部分行被丢弃弹确认后才允许推送
- 入队前:结构不符、必填字段缺失、items/groups/country_codes 为空数组、
行数页数为 0、JSON 不安全值(NaN/Infinity/BigInt/循环引用/数组洞)
覆盖 11 个推 Python 队列的 Tab 与 dedupe/split/convert 三个纯 Java Tab。
闸位按 Tab 挑选以免留下孤儿后端状态:collect-data 校验前置到
activateCollectDataTask 之前(任务保持 PENDING 无需回滚)、product-risk 的国家
检查提到建任务之前;已建任务后才拦下的复用各 Tab 原有失败补偿路径。
两处边界:对象属性 undefined 放行(taskNo 这类可选字段是惯用写法),只拦数组
元素 undefined 与数组洞;price-track 的 asin_rows_by_country 仅在 mode=asin
时要求非空,status 模式下 loadAsinRowsForAppClient 本就返回 {}。
顺带修复 similar-asin / appearance-patent 的 selectFiles 缺少 try/catch,
上传失败会残留上一批文件与解析结果。
测试:tests/dispatch-guard.test.ts 新增 37 个 test_task_101_* 用例。
This commit is contained in:
@@ -356,6 +356,8 @@ import { getPywebviewApi } from "@/shared/bridges/pywebview";
|
||||
import { getTaskPollIntervalMs } from "@/shared/task-progress-config";
|
||||
import { createCategorizedTimers } from "@/shared/utils/categorized-timers";
|
||||
import { saveUrlWithProgress } from "@/shared/utils/download-progress";
|
||||
import { checkQueuePayload } from "@/shared/dispatch-guard";
|
||||
import { passGuard } from "@/shared/dispatch-guard-ui";
|
||||
import ZiniaoVersionSetting from "@/shared/components/ZiniaoVersionSetting.vue";
|
||||
import { useZiniaoVersion } from "@/shared/utils/ziniao-version";
|
||||
|
||||
@@ -1161,6 +1163,27 @@ async function processQueue() {
|
||||
const payload = buildQueuePayload(created.taskId, nextBatch);
|
||||
queuePayloadText.value = JSON.stringify(payload, null, 2);
|
||||
|
||||
const guard = checkQueuePayload(payload, {
|
||||
expectedType: "withdraw-run",
|
||||
requiredDataKeys: ["task_id"],
|
||||
nonEmptyArrayKeys: ["items"],
|
||||
});
|
||||
if (!(await passGuard(guard))) {
|
||||
await submitWithdrawTaskResult(created.taskId, {
|
||||
shops: nextBatch.items.map((item) => ({
|
||||
shopName: item.shopName || "",
|
||||
error: `任务 ${created.taskId} 数据校验未通过,已阻止推送`,
|
||||
shopDone: true,
|
||||
submissionId: createSubmissionId(created.taskId, item.shopName),
|
||||
rows: [],
|
||||
})),
|
||||
});
|
||||
await refreshTaskViews();
|
||||
queuePushResult.value = `任务 ${created.taskId} 数据校验未通过,已阻止推送并继续下一个任务`;
|
||||
clearActiveQueueTask();
|
||||
continue;
|
||||
}
|
||||
|
||||
const pushResult = await api.enqueue_json(payload);
|
||||
if (!pushResult?.success) {
|
||||
await submitWithdrawTaskResult(created.taskId, {
|
||||
|
||||
Reference in New Issue
Block a user