From 0198f5031462078c7e7be42c4bb68d4b28dc3a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=AC=E6=98=8E?= <83812544+Ed1s0nZ@users.noreply.github.com> Date: Wed, 24 Jun 2026 01:43:37 +0800 Subject: [PATCH] Add files via upload --- web/static/i18n/en-US.json | 8 +++- web/static/i18n/zh-CN.json | 8 +++- web/static/js/tasks.js | 77 ++++++++++++++++++++++++++++++++++++++ web/templates/index.html | 5 +++ 4 files changed, 94 insertions(+), 4 deletions(-) diff --git a/web/static/i18n/en-US.json b/web/static/i18n/en-US.json index 30079a96..1f2b4556 100644 --- a/web/static/i18n/en-US.json +++ b/web/static/i18n/en-US.json @@ -2580,6 +2580,8 @@ "agentModeSingle": "Single-agent (Eino ADK)", "agentModeMulti": "Multi-agent (Eino)", "agentModeHint": "Same as chat: Eino single-agent (ADK), or Deep / Plan-Execute / Supervisor (last three require multi_agent.enabled).", + "concurrency": "Concurrency", + "concurrencyHint": "Number of subtasks to run in parallel (1-8). Default 1 is serial; use 1-2 for scan-heavy tasks.", "scheduleMode": "Schedule mode", "scheduleModeManual": "Manual", "scheduleModeCron": "Cron expression", @@ -2594,8 +2596,8 @@ "tasksList": "Task list (one task per line)", "tasksListPlaceholder": "Enter task list, one per line", "tasksListPlaceholderExample": "Enter task list, one per line, for example:\nScan open ports of 192.168.1.1\nCheck if https://example.com has SQL injection\nEnumerate subdomains of example.com", - "tasksListHint": "Enter one task command per line; the system will execute them in order. Empty lines are ignored.", - "tasksListHintFull": "Hint: Enter one task command per line; the system will execute these tasks in order. Empty lines are ignored.", + "tasksListHint": "Enter one task command per line; the system runs them via a concurrency pool. Empty lines are ignored.", + "tasksListHintFull": "Hint: Enter one task command per line; the system runs them via a concurrency pool. Empty lines are ignored.", "createQueue": "Create queue" }, "batchQueueDetailModal": { @@ -2629,6 +2631,8 @@ "scheduleToggleFailed": "Failed to update schedule toggle", "completedAt": "Completed at", "taskTotal": "Total tasks", + "concurrency": "Concurrency", + "concurrencyEditHint": "Click to edit. Cannot change while the queue is running.", "taskList": "Task list", "startLabel": "Start", "completeLabel": "Complete", diff --git a/web/static/i18n/zh-CN.json b/web/static/i18n/zh-CN.json index 497adab6..f40f8a03 100644 --- a/web/static/i18n/zh-CN.json +++ b/web/static/i18n/zh-CN.json @@ -2568,6 +2568,8 @@ "agentModeSingle": "单代理(Eino ADK)", "agentModeMulti": "多代理(Eino)", "agentModeHint": "与对话页一致:Eino 单代理(ADK),或 Deep / Plan-Execute / Supervisor(后三种需已启用多代理)。", + "concurrency": "并发数", + "concurrencyHint": "同时执行的子任务数量(1-8)。默认 1 为串行;含扫描类工具时建议 1-2。", "scheduleMode": "调度方式", "scheduleModeManual": "手工执行", "scheduleModeCron": "调度表达式(Cron)", @@ -2582,8 +2584,8 @@ "tasksList": "任务列表(每行一个任务)", "tasksListPlaceholder": "请输入任务列表,每行一个任务", "tasksListPlaceholderExample": "请输入任务列表,每行一个任务,例如:\n扫描 192.168.1.1 的开放端口\n检查 https://example.com 是否存在SQL注入\n枚举 example.com 的子域名", - "tasksListHint": "每行输入一个任务指令,系统将依次执行这些任务。空行会被自动忽略。", - "tasksListHintFull": "提示:每行输入一个任务指令,系统将依次执行这些任务。空行会被自动忽略。", + "tasksListHint": "每行输入一个任务指令,系统将按并发池执行这些任务。空行会被自动忽略。", + "tasksListHintFull": "提示:每行输入一个任务指令,系统将按并发池执行这些任务。空行会被自动忽略。", "createQueue": "创建队列" }, "batchQueueDetailModal": { @@ -2617,6 +2619,8 @@ "scheduleToggleFailed": "更新调度开关失败", "completedAt": "完成时间", "taskTotal": "任务总数", + "concurrency": "并发数", + "concurrencyEditHint": "点击可修改;队列运行中不可改。", "taskList": "任务列表", "startLabel": "开始", "completeLabel": "完成", diff --git a/web/static/js/tasks.js b/web/static/js/tasks.js index a1389a6f..7af962e9 100644 --- a/web/static/js/tasks.js +++ b/web/static/js/tasks.js @@ -990,6 +990,7 @@ async function createBatchQueue() { const roleSelect = document.getElementById('batch-queue-role'); const projectSelect = document.getElementById('batch-queue-project-id'); const agentModeSelect = document.getElementById('batch-queue-agent-mode'); + const concurrencyInput = document.getElementById('batch-queue-concurrency'); const scheduleModeSelect = document.getElementById('batch-queue-schedule-mode'); const cronExprInput = document.getElementById('batch-queue-cron-expr'); const executeNowCheckbox = document.getElementById('batch-queue-execute-now'); @@ -1019,6 +1020,9 @@ async function createBatchQueue() { const scheduleMode = scheduleModeSelect ? (scheduleModeSelect.value === 'cron' ? 'cron' : 'manual') : 'manual'; const cronExpr = cronExprInput ? cronExprInput.value.trim() : ''; const executeNow = executeNowCheckbox ? !!executeNowCheckbox.checked : false; + let concurrency = concurrencyInput ? parseInt(concurrencyInput.value, 10) : 1; + if (!Number.isFinite(concurrency) || concurrency < 1) concurrency = 1; + if (concurrency > 8) concurrency = 8; if (scheduleMode === 'cron' && !cronExpr) { alert(_t('batchImportModal.cronExprRequired')); return; @@ -1043,6 +1047,7 @@ async function createBatchQueue() { cronExpr, executeNow, projectId, + concurrency, }), }); @@ -1489,6 +1494,7 @@ async function showBatchQueueDetail(queueId) {