From 4345f3085ecde8374100d022d022c1a2ddd37129 Mon Sep 17 00:00:00 2001 From: 666ghj <670939375@qq.com> Date: Fri, 12 Dec 2025 11:41:33 +0800 Subject: [PATCH] Enhance simulation preparation process and frontend display for improved user experience - Added synchronous retrieval of entity count before starting background tasks in simulation.py, allowing immediate access to expected agent totals for the frontend. - Updated the simulation state to include expected entity count and types, enhancing the information available during preparation. - Modified Step2EnvSetup.vue to display a pending status when the simulation is in progress and adjusted the simulation rounds configuration to dynamically reflect calculated values. - Improved the slider for custom rounds to ensure it adapts to the auto-generated maximum rounds, enhancing usability and clarity. --- backend/app/api/simulation.py | 25 ++++++++++++-- frontend/src/components/Step2EnvSetup.vue | 41 ++++++++++++++--------- 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/backend/app/api/simulation.py b/backend/app/api/simulation.py index e90f354..c7ef7f0 100644 --- a/backend/app/api/simulation.py +++ b/backend/app/api/simulation.py @@ -467,6 +467,25 @@ def prepare_simulation(): use_llm_for_profiles = data.get('use_llm_for_profiles', True) parallel_profile_count = data.get('parallel_profile_count', 5) + # ========== 同步获取实体数量(在后台任务启动前) ========== + # 这样前端在调用prepare后立即就能获取到预期Agent总数 + try: + logger.info(f"同步获取实体数量: graph_id={state.graph_id}") + reader = ZepEntityReader() + # 快速读取实体(不需要边信息,只统计数量) + filtered_preview = reader.filter_defined_entities( + graph_id=state.graph_id, + defined_entity_types=entity_types_list, + enrich_with_edges=False # 不获取边信息,加快速度 + ) + # 保存实体数量到状态(供前端立即获取) + state.entities_count = filtered_preview.filtered_count + state.entity_types = list(filtered_preview.entity_types) + logger.info(f"预期实体数量: {filtered_preview.filtered_count}, 类型: {filtered_preview.entity_types}") + except Exception as e: + logger.warning(f"同步获取实体数量失败(将在后台任务中重试): {e}") + # 失败不影响后续流程,后台任务会重新获取 + # 创建异步任务 task_manager = TaskManager() task_id = task_manager.create_task( @@ -477,7 +496,7 @@ def prepare_simulation(): } ) - # 更新模拟状态 + # 更新模拟状态(包含预先获取的实体数量) state.status = SimulationStatus.PREPARING manager._save_simulation_state(state) @@ -594,7 +613,9 @@ def prepare_simulation(): "task_id": task_id, "status": "preparing", "message": "准备任务已启动,请通过 /api/simulation/prepare/status 查询进度", - "already_prepared": False + "already_prepared": False, + "expected_entities_count": state.entities_count, # 预期的Agent总数 + "entity_types": state.entity_types # 实体类型列表 } }) diff --git a/frontend/src/components/Step2EnvSetup.vue b/frontend/src/components/Step2EnvSetup.vue index caae2f9..79475b4 100644 --- a/frontend/src/components/Step2EnvSetup.vue +++ b/frontend/src/components/Step2EnvSetup.vue @@ -427,6 +427,7 @@
进行中 + 等待
@@ -434,8 +435,8 @@

POST /api/simulation/start

模拟环境已准备完成,可以开始运行模拟

- -
+ +
模拟轮数设定 @@ -465,10 +466,10 @@ type="range" v-model.number="customMaxRounds" min="10" - max="120" + :max="autoGeneratedRounds" step="5" class="minimal-slider" - :style="{ '--percent': ((customMaxRounds - 10) / (120 - 10)) * 100 + '%' }" + :style="{ '--percent': ((customMaxRounds - 10) / (autoGeneratedRounds - 10)) * 100 + '%' }" />
10 @@ -476,9 +477,9 @@ class="mark-recommend" :class="{ active: customMaxRounds === 40 }" @click="customMaxRounds = 40" - :style="{ position: 'absolute', left: 'calc(27.27% - 30px)' }" + :style="{ position: 'absolute', left: `calc(${(40 - 10) / (autoGeneratedRounds - 10) * 100}% - 30px)` }" >40 (推荐) - 120 + {{ autoGeneratedRounds }}
@@ -665,7 +666,6 @@ const showProfilesDetail = ref(true) // 模拟轮数配置 const useCustomRounds = ref(false) // 默认使用自动配置轮数 const customMaxRounds = ref(40) // 默认推荐40轮 -const autoGeneratedRounds = ref(120) // 自动生成的轮数(从配置中读取) // Watch stage to update phase watch(currentStage, (newStage) => { @@ -683,15 +683,20 @@ watch(currentStage, (newStage) => { } }) -// Watch simulationConfig to update autoGeneratedRounds -watch(simulationConfig, (newConfig) => { - if (newConfig?.time_config) { - const totalHours = newConfig.time_config.total_simulation_hours || 120 - const minutesPerRound = newConfig.time_config.minutes_per_round || 60 - const calculatedRounds = Math.floor((totalHours * 60) / minutesPerRound) - autoGeneratedRounds.value = calculatedRounds || 120 +// 从配置中计算自动生成的轮数(不使用硬编码默认值) +const autoGeneratedRounds = computed(() => { + if (!simulationConfig.value?.time_config) { + return null // 配置未生成时返回 null } -}, { immediate: true }) + const totalHours = simulationConfig.value.time_config.total_simulation_hours + const minutesPerRound = simulationConfig.value.time_config.minutes_per_round + if (!totalHours || !minutesPerRound) { + return null // 配置数据不完整时返回 null + } + const calculatedRounds = Math.floor((totalHours * 60) / minutesPerRound) + // 确保最大轮数不小于40(推荐值),避免滑动条范围异常 + return Math.max(calculatedRounds, 40) +}) // Polling timer let pollTimer = null @@ -786,6 +791,12 @@ const startPrepareSimulation = async () => { taskId.value = res.data.task_id addLog(`准备任务已启动: ${res.data.task_id}`) + // 立即设置预期Agent总数(从prepare接口返回值获取) + if (res.data.expected_entities_count) { + expectedTotal.value = res.data.expected_entities_count + addLog(`预期Agent总数: ${res.data.expected_entities_count}`) + } + // 开始轮询进度 startPolling() // 开始实时获取 Profiles