Enhance simulation file management and frontend status display
- Updated SimulationRunner to include additional files for deletion, specifically Twitter and Reddit simulation databases, and environment status files. - Refactored Step3Simulation component to streamline the status display, removing unnecessary conditions and improving the user interface for simulation phases. - Introduced a reset function to clear all simulation states before starting a new simulation, ensuring a clean environment for each run.
This commit is contained in:
parent
ec418c1def
commit
d768fd1ea2
2 changed files with 35 additions and 161 deletions
|
|
@ -1053,6 +1053,9 @@ class SimulationRunner:
|
||||||
- reddit/actions.jsonl
|
- reddit/actions.jsonl
|
||||||
- simulation.log
|
- simulation.log
|
||||||
- stdout.log / stderr.log
|
- stdout.log / stderr.log
|
||||||
|
- twitter_simulation.db(模拟数据库)
|
||||||
|
- reddit_simulation.db(模拟数据库)
|
||||||
|
- env_status.json(环境状态)
|
||||||
|
|
||||||
注意:不会删除配置文件(simulation_config.json)和 profile 文件
|
注意:不会删除配置文件(simulation_config.json)和 profile 文件
|
||||||
|
|
||||||
|
|
@ -1072,12 +1075,15 @@ class SimulationRunner:
|
||||||
cleaned_files = []
|
cleaned_files = []
|
||||||
errors = []
|
errors = []
|
||||||
|
|
||||||
# 要删除的文件列表
|
# 要删除的文件列表(包括数据库文件)
|
||||||
files_to_delete = [
|
files_to_delete = [
|
||||||
"run_state.json",
|
"run_state.json",
|
||||||
"simulation.log",
|
"simulation.log",
|
||||||
"stdout.log",
|
"stdout.log",
|
||||||
"stderr.log",
|
"stderr.log",
|
||||||
|
"twitter_simulation.db", # Twitter 平台数据库
|
||||||
|
"reddit_simulation.db", # Reddit 平台数据库
|
||||||
|
"env_status.json", # 环境状态文件
|
||||||
]
|
]
|
||||||
|
|
||||||
# 要删除的目录列表(包含动作日志)
|
# 要删除的目录列表(包含动作日志)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="simulation-panel">
|
<div class="simulation-panel">
|
||||||
<!-- Top Control Bar -->
|
<!-- Top Control Bar -->
|
||||||
<div class="control-bar">
|
<div class="control-bar">
|
||||||
<div class="status-group" v-if="phase >= 1">
|
<div class="status-group">
|
||||||
<!-- Twitter 平台进度 -->
|
<!-- Twitter 平台进度 -->
|
||||||
<div class="platform-status twitter" :class="{ active: runStatus.twitter_running, completed: runStatus.twitter_completed }">
|
<div class="platform-status twitter" :class="{ active: runStatus.twitter_running, completed: runStatus.twitter_completed }">
|
||||||
<div class="platform-header">
|
<div class="platform-header">
|
||||||
|
|
@ -50,80 +50,22 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Phase 0 时显示简单状态 -->
|
|
||||||
<div class="status-group" v-else>
|
|
||||||
<div class="status-item">
|
|
||||||
<span class="label">ROUND</span>
|
|
||||||
<span class="value mono">0<span class="total">/{{ maxRounds || '-' }}</span></span>
|
|
||||||
</div>
|
|
||||||
<div class="status-item">
|
|
||||||
<span class="label">TIME</span>
|
|
||||||
<span class="value mono">0<span class="unit">h</span></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="action-controls">
|
<div class="action-controls">
|
||||||
<button
|
<button
|
||||||
v-if="phase === 0"
|
|
||||||
class="ctrl-btn start"
|
|
||||||
:disabled="isStarting"
|
|
||||||
@click="doStartSimulation"
|
|
||||||
>
|
|
||||||
<span v-if="isStarting" class="spinner-sm"></span>
|
|
||||||
{{ isStarting ? 'INITIALIZING...' : 'START ENGINE' }}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
v-if="phase === 1"
|
|
||||||
class="ctrl-btn stop"
|
|
||||||
:disabled="isStopping"
|
|
||||||
@click="handleStopSimulation"
|
|
||||||
>
|
|
||||||
{{ isStopping ? 'STOPPING...' : 'STOP SIMULATION' }}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
v-if="phase === 2"
|
|
||||||
class="ctrl-btn next"
|
class="ctrl-btn next"
|
||||||
|
:disabled="phase !== 2"
|
||||||
@click="handleNextStep"
|
@click="handleNextStep"
|
||||||
>
|
>
|
||||||
GENERATE REPORT ➝
|
<span v-if="phase !== 2" class="spinner-sm running"></span>
|
||||||
|
{{ phase === 2 ? 'GENERATE REPORT ➝' : 'SIMULATING...' }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Main Content: Dual Timeline or Start Screen -->
|
<!-- Main Content: Dual Timeline -->
|
||||||
<div class="main-content-area" ref="scrollContainer">
|
<div class="main-content-area" ref="scrollContainer">
|
||||||
<!-- Start Screen (Phase 0) -->
|
<!-- Timeline Feed -->
|
||||||
<div v-if="phase === 0" class="start-screen">
|
<div class="timeline-feed">
|
||||||
<div class="engine-status">
|
|
||||||
<div class="engine-icon">⚡️</div>
|
|
||||||
<h2>Simulation Engine Ready</h2>
|
|
||||||
<p>Initialize the dual-platform parallel simulation environment.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="config-grid">
|
|
||||||
<div class="config-card">
|
|
||||||
<span class="label">SIMULATION ID</span>
|
|
||||||
<span class="val mono">{{ simulationId }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="config-card">
|
|
||||||
<span class="label">TARGET ROUNDS</span>
|
|
||||||
<span class="val">{{ maxRounds || 'AUTO' }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="config-card">
|
|
||||||
<span class="label">PLATFORMS</span>
|
|
||||||
<span class="val">Twitter + Reddit</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="startError" class="error-banner">
|
|
||||||
{{ startError }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Timeline Feed (Phase >= 1) -->
|
|
||||||
<div v-else class="timeline-feed">
|
|
||||||
<div class="timeline-axis"></div>
|
<div class="timeline-axis"></div>
|
||||||
|
|
||||||
<TransitionGroup name="timeline-item">
|
<TransitionGroup name="timeline-item">
|
||||||
|
|
@ -238,6 +180,19 @@ const addLog = (msg) => {
|
||||||
emit('add-log', msg)
|
emit('add-log', msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 重置所有状态(用于重新启动模拟)
|
||||||
|
const resetAllState = () => {
|
||||||
|
phase.value = 0
|
||||||
|
runStatus.value = {}
|
||||||
|
recentActions.value = []
|
||||||
|
prevTwitterRound.value = 0
|
||||||
|
prevRedditRound.value = 0
|
||||||
|
startError.value = null
|
||||||
|
isStarting.value = false
|
||||||
|
isStopping.value = false
|
||||||
|
stopPolling() // 停止之前可能存在的轮询
|
||||||
|
}
|
||||||
|
|
||||||
// 启动模拟
|
// 启动模拟
|
||||||
const doStartSimulation = async () => {
|
const doStartSimulation = async () => {
|
||||||
if (!props.simulationId) {
|
if (!props.simulationId) {
|
||||||
|
|
@ -245,6 +200,9 @@ const doStartSimulation = async () => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 先重置所有状态,确保不会受到上一次模拟的影响
|
||||||
|
resetAllState()
|
||||||
|
|
||||||
isStarting.value = true
|
isStarting.value = true
|
||||||
startError.value = null
|
startError.value = null
|
||||||
addLog('正在启动双平台并行模拟...')
|
addLog('正在启动双平台并行模拟...')
|
||||||
|
|
@ -522,30 +480,6 @@ onUnmounted(() => {
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-item {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-item .label {
|
|
||||||
font-size: 10px;
|
|
||||||
color: #999;
|
|
||||||
font-weight: 600;
|
|
||||||
letter-spacing: 0.5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-item .value {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 700;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-item .total, .status-item .unit {
|
|
||||||
font-size: 12px;
|
|
||||||
color: #999;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 双平台进度卡片 */
|
/* 双平台进度卡片 */
|
||||||
.platform-status {
|
.platform-status {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -649,16 +583,6 @@ onUnmounted(() => {
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ctrl-btn.start {
|
|
||||||
background: #000;
|
|
||||||
color: #FFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ctrl-btn.stop {
|
|
||||||
background: #FFEBEE;
|
|
||||||
color: #C62828;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ctrl-btn.next {
|
.ctrl-btn.next {
|
||||||
background: #E8F5E9;
|
background: #E8F5E9;
|
||||||
color: #2E7D32;
|
color: #2E7D32;
|
||||||
|
|
@ -682,67 +606,6 @@ onUnmounted(() => {
|
||||||
background: #FAFAFA;
|
background: #FAFAFA;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start Screen */
|
|
||||||
.start-screen {
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.engine-status {
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.engine-icon {
|
|
||||||
font-size: 48px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.engine-status h2 {
|
|
||||||
font-size: 24px;
|
|
||||||
font-weight: 700;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.engine-status p {
|
|
||||||
color: #666;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(3, 1fr);
|
|
||||||
gap: 16px;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 600px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-card {
|
|
||||||
background: #FFF;
|
|
||||||
padding: 16px;
|
|
||||||
border-radius: 8px;
|
|
||||||
border: 1px solid #EAEAEA;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-card .label {
|
|
||||||
display: block;
|
|
||||||
font-size: 10px;
|
|
||||||
color: #999;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-card .val {
|
|
||||||
display: block;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- Timeline Feed --- */
|
/* --- Timeline Feed --- */
|
||||||
.timeline-feed {
|
.timeline-feed {
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
|
|
@ -1018,6 +881,11 @@ onUnmounted(() => {
|
||||||
animation: spin 0.8s linear infinite;
|
animation: spin 0.8s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.spinner-sm.running {
|
||||||
|
border: 2px solid rgba(46, 125, 50, 0.3);
|
||||||
|
border-top-color: #2E7D32;
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes spin {
|
@keyframes spin {
|
||||||
to { transform: rotate(360deg); }
|
to { transform: rotate(360deg); }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue