Implement simulation environment management features in frontend
- Added new API functions for closing the simulation environment and retrieving its status. - Enhanced the SimulationRunView and SimulationView components to gracefully handle simulation termination when navigating between steps. - Introduced logging for better user feedback during the simulation closure process, including attempts to force stop if graceful closure fails.
This commit is contained in:
parent
0577ecdae8
commit
ec418c1def
3 changed files with 132 additions and 4 deletions
|
|
@ -152,3 +152,19 @@ export const getSimulationActions = (simulationId, params = {}) => {
|
|||
return service.get(`/api/simulation/${simulationId}/actions`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭模拟环境(优雅退出)
|
||||
* @param {Object} data - { simulation_id, timeout? }
|
||||
*/
|
||||
export const closeSimulationEnv = (data) => {
|
||||
return service.post('/api/simulation/close-env', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模拟环境状态
|
||||
* @param {Object} data - { simulation_id }
|
||||
*/
|
||||
export const getEnvStatus = (data) => {
|
||||
return service.post('/api/simulation/env-status', data)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ import { useRoute, useRouter } from 'vue-router'
|
|||
import GraphPanel from '../components/GraphPanel.vue'
|
||||
import Step3Simulation from '../components/Step3Simulation.vue'
|
||||
import { getProject, getGraphData } from '../api/graph'
|
||||
import { getSimulation } from '../api/simulation'
|
||||
import { getSimulation, stopSimulation, closeSimulationEnv, getEnvStatus } from '../api/simulation'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
|
@ -142,7 +142,50 @@ const toggleMaximize = (target) => {
|
|||
}
|
||||
}
|
||||
|
||||
const handleGoBack = () => {
|
||||
const handleGoBack = async () => {
|
||||
// 在返回 Step 2 之前,先关闭正在运行的模拟
|
||||
addLog('准备返回 Step 2,正在关闭模拟...')
|
||||
|
||||
// 停止轮询
|
||||
stopGraphRefresh()
|
||||
|
||||
try {
|
||||
// 先尝试优雅关闭模拟环境
|
||||
const envStatusRes = await getEnvStatus({ simulation_id: currentSimulationId.value })
|
||||
|
||||
if (envStatusRes.success && envStatusRes.data?.env_alive) {
|
||||
addLog('正在关闭模拟环境...')
|
||||
try {
|
||||
await closeSimulationEnv({
|
||||
simulation_id: currentSimulationId.value,
|
||||
timeout: 10
|
||||
})
|
||||
addLog('✓ 模拟环境已关闭')
|
||||
} catch (closeErr) {
|
||||
addLog(`关闭模拟环境失败,尝试强制停止...`)
|
||||
try {
|
||||
await stopSimulation({ simulation_id: currentSimulationId.value })
|
||||
addLog('✓ 模拟已强制停止')
|
||||
} catch (stopErr) {
|
||||
addLog(`强制停止失败: ${stopErr.message}`)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 环境未运行,检查是否需要停止进程
|
||||
if (isSimulating.value) {
|
||||
addLog('正在停止模拟进程...')
|
||||
try {
|
||||
await stopSimulation({ simulation_id: currentSimulationId.value })
|
||||
addLog('✓ 模拟已停止')
|
||||
} catch (err) {
|
||||
addLog(`停止模拟失败: ${err.message}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
addLog(`检查模拟状态失败: ${err.message}`)
|
||||
}
|
||||
|
||||
// 返回到 Step 2 (环境搭建)
|
||||
router.push({ name: 'Simulation', params: { simulationId: currentSimulationId.value } })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ import { useRoute, useRouter } from 'vue-router'
|
|||
import GraphPanel from '../components/GraphPanel.vue'
|
||||
import Step2EnvSetup from '../components/Step2EnvSetup.vue'
|
||||
import { getProject, getGraphData } from '../api/graph'
|
||||
import { getSimulation } from '../api/simulation'
|
||||
import { getSimulation, stopSimulation, getEnvStatus, closeSimulationEnv } from '../api/simulation'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
|
@ -171,6 +171,70 @@ const handleNextStep = (params = {}) => {
|
|||
}
|
||||
|
||||
// --- Data Logic ---
|
||||
|
||||
/**
|
||||
* 检查并关闭正在运行的模拟
|
||||
* 当用户从 Step 3 返回到 Step 2 时,默认用户要退出模拟
|
||||
*/
|
||||
const checkAndStopRunningSimulation = async () => {
|
||||
if (!currentSimulationId.value) return
|
||||
|
||||
try {
|
||||
// 先检查模拟环境是否存活
|
||||
const envStatusRes = await getEnvStatus({ simulation_id: currentSimulationId.value })
|
||||
|
||||
if (envStatusRes.success && envStatusRes.data?.env_alive) {
|
||||
addLog('检测到模拟环境正在运行,正在关闭...')
|
||||
|
||||
// 尝试优雅关闭模拟环境
|
||||
try {
|
||||
const closeRes = await closeSimulationEnv({
|
||||
simulation_id: currentSimulationId.value,
|
||||
timeout: 10 // 10秒超时
|
||||
})
|
||||
|
||||
if (closeRes.success) {
|
||||
addLog('✓ 模拟环境已关闭')
|
||||
} else {
|
||||
addLog(`关闭模拟环境失败: ${closeRes.error || '未知错误'}`)
|
||||
// 如果优雅关闭失败,尝试强制停止
|
||||
await forceStopSimulation()
|
||||
}
|
||||
} catch (closeErr) {
|
||||
addLog(`关闭模拟环境异常: ${closeErr.message}`)
|
||||
// 如果优雅关闭异常,尝试强制停止
|
||||
await forceStopSimulation()
|
||||
}
|
||||
} else {
|
||||
// 环境未运行,但可能进程还在,检查模拟状态
|
||||
const simRes = await getSimulation(currentSimulationId.value)
|
||||
if (simRes.success && simRes.data?.status === 'running') {
|
||||
addLog('检测到模拟状态为运行中,正在停止...')
|
||||
await forceStopSimulation()
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
// 检查环境状态失败不影响后续流程
|
||||
console.warn('检查模拟状态失败:', err)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 强制停止模拟
|
||||
*/
|
||||
const forceStopSimulation = async () => {
|
||||
try {
|
||||
const stopRes = await stopSimulation({ simulation_id: currentSimulationId.value })
|
||||
if (stopRes.success) {
|
||||
addLog('✓ 模拟已强制停止')
|
||||
} else {
|
||||
addLog(`强制停止模拟失败: ${stopRes.error || '未知错误'}`)
|
||||
}
|
||||
} catch (err) {
|
||||
addLog(`强制停止模拟异常: ${err.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
const loadSimulationData = async () => {
|
||||
try {
|
||||
addLog(`加载模拟数据: ${currentSimulationId.value}`)
|
||||
|
|
@ -222,8 +286,13 @@ const refreshGraph = () => {
|
|||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
onMounted(async () => {
|
||||
addLog('SimulationView 初始化')
|
||||
|
||||
// 检查并关闭正在运行的模拟(用户从 Step 3 返回时)
|
||||
await checkAndStopRunningSimulation()
|
||||
|
||||
// 加载模拟数据
|
||||
loadSimulationData()
|
||||
})
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in a new issue