修复执行环境编辑更新功能和编译错误
主要修复内容: 1. 修复执行环境编辑更新功能 - 简化前端更新逻辑,直接传递所有字段而非复杂的条件判断 - 添加详细的调试日志用于问题排查 - 修复数据刷新机制,保存后自动刷新页面 - 完善错误处理和用户提示 2. 修复编译错误 - 修复 sysinfo 0.30 API 变化问题 - 修复 ExecutionStatistics 字段不匹配问题 - 添加 chrono::Timelike trait 导入 - 修复 MutexGuard 所有权问题 3. 完善环境管理功能 - 实现健康检查命令 health_check_execution_environment - 完善删除、激活状态切换等功能 - 添加确认对话框和成功提示 4. 修复数据序列化问题 - 移除 environment_type 字段的 serde rename 属性 - 确保前后端数据格式一致 技术细节: - 后端使用 UniversalWorkflowService 支持多环境管理 - 前端使用 window.location.reload() 临时解决数据刷新问题 - 添加详细日志便于调试和问题排查
This commit is contained in:
44
Cargo.lock
generated
44
Cargo.lock
generated
@@ -2571,6 +2571,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
"sha2",
|
"sha2",
|
||||||
|
"sysinfo",
|
||||||
"tauri",
|
"tauri",
|
||||||
"tauri-build",
|
"tauri-build",
|
||||||
"tauri-plugin-dialog",
|
"tauri-plugin-dialog",
|
||||||
@@ -2686,6 +2687,15 @@ version = "0.1.14"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ntapi"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nu-ansi-term"
|
name = "nu-ansi-term"
|
||||||
version = "0.46.0"
|
version = "0.46.0"
|
||||||
@@ -4440,6 +4450,21 @@ dependencies = [
|
|||||||
"syn 2.0.104",
|
"syn 2.0.104",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sysinfo"
|
||||||
|
version = "0.30.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0a5b4ddaee55fb2bea2bf0e5000747e5f5c0de765e5a5ff87f4cd106439f4bb3"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
"ntapi",
|
||||||
|
"once_cell",
|
||||||
|
"rayon",
|
||||||
|
"windows 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "system-configuration"
|
name = "system-configuration"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
@@ -5825,6 +5850,16 @@ dependencies = [
|
|||||||
"windows-version",
|
"windows-version",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
|
||||||
|
dependencies = [
|
||||||
|
"windows-core 0.52.0",
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows"
|
name = "windows"
|
||||||
version = "0.58.0"
|
version = "0.58.0"
|
||||||
@@ -5857,6 +5892,15 @@ dependencies = [
|
|||||||
"windows-core 0.61.2",
|
"windows-core 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-core"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-core"
|
name = "windows-core"
|
||||||
version = "0.58.0"
|
version = "0.58.0"
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ url = "2.5.4"
|
|||||||
urlencoding = "2.1"
|
urlencoding = "2.1"
|
||||||
bincode = "1.3"
|
bincode = "1.3"
|
||||||
zip = "0.6"
|
zip = "0.6"
|
||||||
|
sysinfo = "0.30"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winapi = { version = "0.3", features = ["sysinfoapi"] }
|
winapi = { version = "0.3", features = ["sysinfoapi"] }
|
||||||
|
|||||||
@@ -78,10 +78,9 @@ impl From<String> for HealthStatus {
|
|||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct WorkflowExecutionEnvironment {
|
pub struct WorkflowExecutionEnvironment {
|
||||||
pub id: Option<i64>,
|
pub id: Option<i64>,
|
||||||
|
|
||||||
// 基本信息
|
// 基本信息
|
||||||
pub name: String,
|
pub name: String,
|
||||||
#[serde(rename = "type")]
|
|
||||||
pub environment_type: EnvironmentType,
|
pub environment_type: EnvironmentType,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
|
|
||||||
@@ -124,7 +123,6 @@ pub struct WorkflowExecutionEnvironment {
|
|||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct CreateExecutionEnvironmentRequest {
|
pub struct CreateExecutionEnvironmentRequest {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
#[serde(rename = "type")]
|
|
||||||
pub environment_type: EnvironmentType,
|
pub environment_type: EnvironmentType,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub base_url: String,
|
pub base_url: String,
|
||||||
|
|||||||
@@ -259,6 +259,7 @@ impl WorkflowExecutionEnvironmentRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if set_clauses.is_empty() {
|
if set_clauses.is_empty() {
|
||||||
|
info!("没有需要更新的字段,跳过更新,ID: {}", id);
|
||||||
return Ok(()); // 没有需要更新的字段
|
return Ok(()); // 没有需要更新的字段
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,12 +275,14 @@ impl WorkflowExecutionEnvironmentRepository {
|
|||||||
set_clauses.join(", ")
|
set_clauses.join(", ")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
info!("执行更新SQL: {}, 更新字段: {:?}", sql, set_clauses);
|
||||||
|
|
||||||
let param_refs: Vec<&dyn rusqlite::ToSql> = params.iter().map(|p| p.as_ref()).collect();
|
let param_refs: Vec<&dyn rusqlite::ToSql> = params.iter().map(|p| p.as_ref()).collect();
|
||||||
|
|
||||||
conn.execute(&sql, param_refs.as_slice())
|
let rows_affected = conn.execute(&sql, param_refs.as_slice())
|
||||||
.map_err(|e| anyhow!("更新工作流执行环境失败: {}", e))?;
|
.map_err(|e| anyhow!("更新工作流执行环境失败: {}", e))?;
|
||||||
|
|
||||||
info!("成功更新工作流执行环境,ID: {}", id);
|
info!("成功更新工作流执行环境,ID: {}, 影响行数: {}", id, rows_affected);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -603,10 +603,12 @@ pub fn run() {
|
|||||||
commands::workflow_commands::get_execution_results,
|
commands::workflow_commands::get_execution_results,
|
||||||
commands::workflow_commands::cancel_execution,
|
commands::workflow_commands::cancel_execution,
|
||||||
commands::workflow_commands::get_execution_history,
|
commands::workflow_commands::get_execution_history,
|
||||||
|
commands::workflow_commands::get_system_statistics,
|
||||||
commands::workflow_commands::get_execution_environments,
|
commands::workflow_commands::get_execution_environments,
|
||||||
commands::workflow_commands::create_execution_environment,
|
commands::workflow_commands::create_execution_environment,
|
||||||
commands::workflow_commands::update_execution_environment,
|
commands::workflow_commands::update_execution_environment,
|
||||||
commands::workflow_commands::delete_execution_environment
|
commands::workflow_commands::delete_execution_environment,
|
||||||
|
commands::workflow_commands::health_check_execution_environment
|
||||||
])
|
])
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
// 初始化日志系统
|
// 初始化日志系统
|
||||||
|
|||||||
@@ -12,8 +12,10 @@ use crate::data::models::workflow_execution_environment::{
|
|||||||
};
|
};
|
||||||
use crate::app_state::AppState;
|
use crate::app_state::AppState;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use tauri::State;
|
use tauri::State;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
use chrono::Timelike;
|
||||||
|
|
||||||
/// 获取所有工作流模板
|
/// 获取所有工作流模板
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@@ -146,19 +148,48 @@ pub async fn execute_workflow_with_mapping(
|
|||||||
.clone()
|
.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
// 创建ComfyUI服务
|
// 使用通用工作流服务(支持环境管理)
|
||||||
let comfyui_settings = crate::config::ComfyUISettings::default();
|
let universal_service = {
|
||||||
let comfyui_service = crate::business::services::comfyui_service::ComfyUIService::new(comfyui_settings);
|
let service_guard = state.get_universal_workflow_service()
|
||||||
|
.map_err(|e| format!("获取通用工作流服务失败: {}", e))?;
|
||||||
|
|
||||||
// 创建工作流执行服务
|
service_guard.as_ref()
|
||||||
let execution_service = crate::business::services::workflow_execution_service::WorkflowExecutionService::new(comfyui_service);
|
.ok_or_else(|| "通用工作流服务未初始化,请先配置执行环境".to_string())?
|
||||||
|
.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
// 转换请求格式到新的统一格式
|
||||||
|
let unified_request = crate::business::services::universal_workflow_service::ExecuteWorkflowRequest {
|
||||||
|
workflow_identifier: format!("template_{}", request.workflow_template_id),
|
||||||
|
version: None,
|
||||||
|
input_data: request.input_data,
|
||||||
|
environment_id: request.execution_environment_id,
|
||||||
|
user_id: None,
|
||||||
|
session_id: None,
|
||||||
|
metadata: request.execution_config_override,
|
||||||
|
};
|
||||||
|
|
||||||
// 执行工作流
|
// 执行工作流
|
||||||
let response = execution_service.execute_workflow(request, &template_repo, &execution_repo).await
|
let response = universal_service.execute_workflow(unified_request).await
|
||||||
.map_err(|e| format!("执行工作流失败: {}", e))?;
|
.map_err(|e| format!("执行工作流失败: {}", e))?;
|
||||||
|
|
||||||
|
// 转换响应格式
|
||||||
|
let converted_response = crate::data::models::outfit_photo_generation::ExecuteWorkflowResponse {
|
||||||
|
execution_id: response.execution_id,
|
||||||
|
status: match response.status {
|
||||||
|
crate::data::models::workflow_execution_record::ExecutionStatus::Running => "running".to_string(),
|
||||||
|
crate::data::models::workflow_execution_record::ExecutionStatus::Completed => "completed".to_string(),
|
||||||
|
crate::data::models::workflow_execution_record::ExecutionStatus::Failed => "failed".to_string(),
|
||||||
|
crate::data::models::workflow_execution_record::ExecutionStatus::Cancelled => "cancelled".to_string(),
|
||||||
|
crate::data::models::workflow_execution_record::ExecutionStatus::Pending => "pending".to_string(),
|
||||||
|
crate::data::models::workflow_execution_record::ExecutionStatus::Timeout => "timeout".to_string(),
|
||||||
|
},
|
||||||
|
comfyui_prompt_id: response.comfyui_prompt_id,
|
||||||
|
error_message: response.error_message,
|
||||||
|
};
|
||||||
|
|
||||||
info!("工作流执行成功,执行记录ID: {}", response.execution_id);
|
info!("工作流执行成功,执行记录ID: {}", response.execution_id);
|
||||||
Ok(response)
|
Ok(converted_response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -275,6 +306,16 @@ pub async fn cancel_execution(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 执行历史分页响应
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct ExecutionHistoryResponse {
|
||||||
|
pub records: Vec<WorkflowExecutionRecord>,
|
||||||
|
pub total_count: u32,
|
||||||
|
pub page: u32,
|
||||||
|
pub page_size: u32,
|
||||||
|
pub total_pages: u32,
|
||||||
|
}
|
||||||
|
|
||||||
/// 获取执行历史
|
/// 获取执行历史
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn get_execution_history(
|
pub async fn get_execution_history(
|
||||||
@@ -282,7 +323,7 @@ pub async fn get_execution_history(
|
|||||||
limit: Option<i32>,
|
limit: Option<i32>,
|
||||||
offset: Option<i32>,
|
offset: Option<i32>,
|
||||||
state: State<'_, AppState>,
|
state: State<'_, AppState>,
|
||||||
) -> Result<Vec<WorkflowExecutionRecord>, String> {
|
) -> Result<ExecutionHistoryResponse, String> {
|
||||||
info!("获取执行历史");
|
info!("获取执行历史");
|
||||||
|
|
||||||
// 获取工作流执行记录仓库
|
// 获取工作流执行记录仓库
|
||||||
@@ -293,19 +334,35 @@ pub async fn get_execution_history(
|
|||||||
.ok_or_else(|| "工作流执行记录仓库未初始化".to_string())?;
|
.ok_or_else(|| "工作流执行记录仓库未初始化".to_string())?;
|
||||||
|
|
||||||
// 查询执行历史
|
// 查询执行历史
|
||||||
let records = if let (Some(limit), Some(offset)) = (limit, offset) {
|
let (records, total_count, page, page_size) = if let (Some(limit), Some(offset)) = (limit, offset) {
|
||||||
let page = (offset / limit.max(1)) as u32;
|
let page = (offset / limit.max(1)) as u32;
|
||||||
let page_size = limit as u32;
|
let page_size = limit as u32;
|
||||||
let (records, _total) = repo.find_with_pagination(filter.as_ref(), page, page_size)
|
let (records, total) = repo.find_with_pagination(filter.as_ref(), page, page_size)
|
||||||
.map_err(|e| format!("分页查询执行历史失败: {}", e))?;
|
.map_err(|e| format!("分页查询执行历史失败: {}", e))?;
|
||||||
records
|
(records, total, page, page_size)
|
||||||
} else {
|
} else {
|
||||||
repo.find_all(filter.as_ref())
|
// 如果没有分页参数,返回所有记录
|
||||||
.map_err(|e| format!("查询执行历史失败: {}", e))?
|
let records = repo.find_all(filter.as_ref())
|
||||||
|
.map_err(|e| format!("查询执行历史失败: {}", e))?;
|
||||||
|
let total = records.len() as u32;
|
||||||
|
(records, total, 0, total)
|
||||||
};
|
};
|
||||||
|
|
||||||
info!("成功获取 {} 条执行历史记录", records.len());
|
let total_pages = if page_size > 0 {
|
||||||
Ok(records)
|
(total_count + page_size - 1) / page_size
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
};
|
||||||
|
|
||||||
|
info!("成功获取 {} 条执行历史记录,总数: {}", records.len(), total_count);
|
||||||
|
|
||||||
|
Ok(ExecutionHistoryResponse {
|
||||||
|
records,
|
||||||
|
total_count,
|
||||||
|
page,
|
||||||
|
page_size,
|
||||||
|
total_pages,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 获取执行环境列表
|
/// 获取执行环境列表
|
||||||
@@ -366,7 +423,7 @@ pub async fn update_execution_environment(
|
|||||||
request: UpdateExecutionEnvironmentRequest,
|
request: UpdateExecutionEnvironmentRequest,
|
||||||
state: State<'_, AppState>,
|
state: State<'_, AppState>,
|
||||||
) -> Result<WorkflowExecutionEnvironment, String> {
|
) -> Result<WorkflowExecutionEnvironment, String> {
|
||||||
info!("更新执行环境: {}", id);
|
info!("更新执行环境: {}, 请求数据: {:?}", id, request);
|
||||||
|
|
||||||
// 获取工作流执行环境仓库
|
// 获取工作流执行环境仓库
|
||||||
let repo_guard = state.get_workflow_execution_environment_repository()
|
let repo_guard = state.get_workflow_execution_environment_repository()
|
||||||
@@ -375,6 +432,13 @@ pub async fn update_execution_environment(
|
|||||||
let repo = repo_guard.as_ref()
|
let repo = repo_guard.as_ref()
|
||||||
.ok_or_else(|| "工作流执行环境仓库未初始化".to_string())?;
|
.ok_or_else(|| "工作流执行环境仓库未初始化".to_string())?;
|
||||||
|
|
||||||
|
// 查询更新前的环境
|
||||||
|
let old_environment = repo.find_by_id(id)
|
||||||
|
.map_err(|e| format!("查询更新前的执行环境失败: {}", e))?
|
||||||
|
.ok_or_else(|| format!("执行环境不存在,ID: {}", id))?;
|
||||||
|
|
||||||
|
info!("更新前的环境数据: {:?}", old_environment);
|
||||||
|
|
||||||
// 更新执行环境
|
// 更新执行环境
|
||||||
repo.update(id, &request)
|
repo.update(id, &request)
|
||||||
.map_err(|e| format!("更新执行环境失败: {}", e))?;
|
.map_err(|e| format!("更新执行环境失败: {}", e))?;
|
||||||
@@ -384,7 +448,7 @@ pub async fn update_execution_environment(
|
|||||||
.map_err(|e| format!("查询更新后的执行环境失败: {}", e))?
|
.map_err(|e| format!("查询更新后的执行环境失败: {}", e))?
|
||||||
.ok_or_else(|| "更新后的执行环境未找到".to_string())?;
|
.ok_or_else(|| "更新后的执行环境未找到".to_string())?;
|
||||||
|
|
||||||
info!("成功更新执行环境,ID: {}", id);
|
info!("成功更新执行环境,ID: {}, 更新后数据: {:?}", id, environment);
|
||||||
Ok(environment)
|
Ok(environment)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,6 +475,43 @@ pub async fn delete_execution_environment(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 健康检查执行环境
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn health_check_execution_environment(
|
||||||
|
id: i64,
|
||||||
|
state: State<'_, AppState>,
|
||||||
|
) -> Result<crate::data::models::workflow_execution_environment::HealthStatus, String> {
|
||||||
|
info!("健康检查执行环境: {}", id);
|
||||||
|
|
||||||
|
// 获取工作流执行环境仓库并克隆以避免所有权问题
|
||||||
|
let repo = {
|
||||||
|
let repo_guard = state.get_workflow_execution_environment_repository()
|
||||||
|
.map_err(|e| format!("获取工作流执行环境仓库失败: {}", e))?;
|
||||||
|
|
||||||
|
repo_guard.as_ref()
|
||||||
|
.ok_or_else(|| "工作流执行环境仓库未初始化".to_string())?
|
||||||
|
.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取环境信息
|
||||||
|
let _environment = repo.find_by_id(id)
|
||||||
|
.map_err(|e| format!("查询执行环境失败: {}", e))?
|
||||||
|
.ok_or_else(|| format!("执行环境不存在,ID: {}", id))?;
|
||||||
|
|
||||||
|
// 执行健康检查 - 使用公共方法
|
||||||
|
let health_results = repo.health_check_all().await
|
||||||
|
.map_err(|e| format!("执行健康检查失败: {}", e))?;
|
||||||
|
|
||||||
|
// 查找当前环境的健康状态
|
||||||
|
let health_status = health_results.iter()
|
||||||
|
.find(|(env_id, _)| *env_id == id)
|
||||||
|
.map(|(_, status)| status.clone())
|
||||||
|
.unwrap_or(crate::data::models::workflow_execution_environment::HealthStatus::Unknown);
|
||||||
|
|
||||||
|
info!("执行环境健康检查完成,ID: {}, 状态: {:?}", id, health_status);
|
||||||
|
Ok(health_status)
|
||||||
|
}
|
||||||
|
|
||||||
/// 导出工作流模板
|
/// 导出工作流模板
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn export_workflow_template(
|
pub async fn export_workflow_template(
|
||||||
@@ -634,6 +735,157 @@ pub async fn delete_execution_result_files(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 系统统计信息响应
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct SystemStatistics {
|
||||||
|
pub execution_stats: ExecutionStats,
|
||||||
|
pub environment_stats: EnvironmentStats,
|
||||||
|
pub system_resources: SystemResources,
|
||||||
|
pub performance_metrics: PerformanceMetrics,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct ExecutionStats {
|
||||||
|
pub total_executions_today: u32,
|
||||||
|
pub successful_executions_today: u32,
|
||||||
|
pub failed_executions_today: u32,
|
||||||
|
pub average_execution_time_seconds: f64,
|
||||||
|
pub current_queue_size: u32,
|
||||||
|
pub active_executions: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct EnvironmentStats {
|
||||||
|
pub total_environments: u32,
|
||||||
|
pub healthy_environments: u32,
|
||||||
|
pub unhealthy_environments: u32,
|
||||||
|
pub average_response_time_ms: f64,
|
||||||
|
pub total_capacity: u32,
|
||||||
|
pub used_capacity: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct SystemResources {
|
||||||
|
pub cpu_usage_percent: f64,
|
||||||
|
pub memory_usage_percent: f64,
|
||||||
|
pub disk_usage_percent: f64,
|
||||||
|
pub network_status: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct PerformanceMetrics {
|
||||||
|
pub requests_per_minute: u32,
|
||||||
|
pub average_response_time_ms: f64,
|
||||||
|
pub error_rate_percent: f64,
|
||||||
|
pub uptime_hours: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取系统统计信息
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn get_system_statistics(
|
||||||
|
state: State<'_, AppState>,
|
||||||
|
) -> Result<SystemStatistics, String> {
|
||||||
|
info!("获取系统统计信息");
|
||||||
|
|
||||||
|
// 获取工作流执行记录仓库
|
||||||
|
let repo_guard = state.get_workflow_execution_record_repository()
|
||||||
|
.map_err(|e| format!("获取工作流执行记录仓库失败: {}", e))?;
|
||||||
|
|
||||||
|
let repo = repo_guard.as_ref()
|
||||||
|
.ok_or_else(|| "工作流执行记录仓库未初始化".to_string())?;
|
||||||
|
|
||||||
|
// 获取环境仓库
|
||||||
|
let env_repo_guard = state.get_workflow_execution_environment_repository()
|
||||||
|
.map_err(|e| format!("获取执行环境仓库失败: {}", e))?;
|
||||||
|
|
||||||
|
let env_repo = env_repo_guard.as_ref()
|
||||||
|
.ok_or_else(|| "执行环境仓库未初始化".to_string())?;
|
||||||
|
|
||||||
|
// 获取今天的执行统计
|
||||||
|
let today = chrono::Utc::now().date_naive();
|
||||||
|
let today_filter = crate::data::models::workflow_execution_record::ExecutionRecordFilter {
|
||||||
|
date_from: Some(today.and_hms_opt(0, 0, 0).unwrap().and_utc()),
|
||||||
|
date_to: Some(today.and_hms_opt(23, 59, 59).unwrap().and_utc()),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let execution_stats_result = repo.get_execution_statistics(Some(&today_filter))
|
||||||
|
.map_err(|e| format!("获取执行统计失败: {}", e))?;
|
||||||
|
|
||||||
|
// 获取环境统计
|
||||||
|
let environments = env_repo.find_all(None)
|
||||||
|
.map_err(|e| format!("获取环境列表失败: {}", e))?;
|
||||||
|
|
||||||
|
let healthy_envs = environments.iter()
|
||||||
|
.filter(|env| env.health_status == crate::data::models::workflow_execution_environment::HealthStatus::Healthy)
|
||||||
|
.count() as u32;
|
||||||
|
|
||||||
|
let total_capacity: u32 = environments.iter()
|
||||||
|
.map(|env| env.max_concurrent_jobs as u32)
|
||||||
|
.sum();
|
||||||
|
|
||||||
|
// 获取当前活跃执行
|
||||||
|
let active_filter = crate::data::models::workflow_execution_record::ExecutionRecordFilter {
|
||||||
|
status: Some(crate::data::models::workflow_execution_record::ExecutionStatus::Running),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let active_executions = repo.find_all(Some(&active_filter))
|
||||||
|
.map_err(|e| format!("获取活跃执行失败: {}", e))?;
|
||||||
|
|
||||||
|
// 获取队列中的执行
|
||||||
|
let pending_filter = crate::data::models::workflow_execution_record::ExecutionRecordFilter {
|
||||||
|
status: Some(crate::data::models::workflow_execution_record::ExecutionStatus::Pending),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let pending_executions = repo.find_all(Some(&pending_filter))
|
||||||
|
.map_err(|e| format!("获取队列执行失败: {}", e))?;
|
||||||
|
|
||||||
|
// 计算系统资源使用情况(简化实现)
|
||||||
|
let cpu_usage = get_cpu_usage().unwrap_or(0.0);
|
||||||
|
let memory_usage = get_memory_usage().unwrap_or(0.0);
|
||||||
|
let disk_usage = get_disk_usage().unwrap_or(0.0);
|
||||||
|
|
||||||
|
Ok(SystemStatistics {
|
||||||
|
execution_stats: ExecutionStats {
|
||||||
|
total_executions_today: execution_stats_result.total_executions,
|
||||||
|
successful_executions_today: execution_stats_result.completed_executions,
|
||||||
|
failed_executions_today: execution_stats_result.failed_executions,
|
||||||
|
average_execution_time_seconds: execution_stats_result.average_duration_seconds.unwrap_or(0.0),
|
||||||
|
current_queue_size: pending_executions.len() as u32,
|
||||||
|
active_executions: active_executions.len() as u32,
|
||||||
|
},
|
||||||
|
environment_stats: EnvironmentStats {
|
||||||
|
total_environments: environments.len() as u32,
|
||||||
|
healthy_environments: healthy_envs,
|
||||||
|
unhealthy_environments: environments.len() as u32 - healthy_envs,
|
||||||
|
average_response_time_ms: environments.iter()
|
||||||
|
.filter_map(|env| env.average_response_time_ms)
|
||||||
|
.map(|t| t as f64)
|
||||||
|
.sum::<f64>() / environments.len().max(1) as f64,
|
||||||
|
total_capacity,
|
||||||
|
used_capacity: active_executions.len() as u32,
|
||||||
|
},
|
||||||
|
system_resources: SystemResources {
|
||||||
|
cpu_usage_percent: cpu_usage,
|
||||||
|
memory_usage_percent: memory_usage,
|
||||||
|
disk_usage_percent: disk_usage,
|
||||||
|
network_status: "connected".to_string(),
|
||||||
|
},
|
||||||
|
performance_metrics: PerformanceMetrics {
|
||||||
|
requests_per_minute: calculate_requests_per_minute(&execution_stats_result),
|
||||||
|
average_response_time_ms: execution_stats_result.average_duration_seconds.unwrap_or(0.0) * 1000.0,
|
||||||
|
error_rate_percent: if execution_stats_result.total_executions > 0 {
|
||||||
|
(execution_stats_result.failed_executions as f64 / execution_stats_result.total_executions as f64) * 100.0
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
},
|
||||||
|
uptime_hours: get_uptime_hours(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// 获取存储统计信息
|
/// 获取存储统计信息
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn get_storage_statistics(
|
pub async fn get_storage_statistics(
|
||||||
@@ -685,3 +937,81 @@ pub async fn batch_cleanup_execution_results(
|
|||||||
errors: Vec::new(),
|
errors: Vec::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 辅助函数:获取CPU使用率
|
||||||
|
fn get_cpu_usage() -> Option<f64> {
|
||||||
|
use sysinfo::System;
|
||||||
|
|
||||||
|
let mut system = System::new_all();
|
||||||
|
system.refresh_cpu();
|
||||||
|
|
||||||
|
// 等待一小段时间以获得准确的CPU使用率
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(200));
|
||||||
|
system.refresh_cpu();
|
||||||
|
|
||||||
|
let cpu_usage: f64 = system.cpus().iter()
|
||||||
|
.map(|cpu| cpu.cpu_usage() as f64)
|
||||||
|
.sum::<f64>() / system.cpus().len() as f64;
|
||||||
|
|
||||||
|
Some(cpu_usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助函数:获取内存使用率
|
||||||
|
fn get_memory_usage() -> Option<f64> {
|
||||||
|
use sysinfo::System;
|
||||||
|
|
||||||
|
let mut system = System::new_all();
|
||||||
|
system.refresh_memory();
|
||||||
|
|
||||||
|
let total_memory = system.total_memory();
|
||||||
|
let used_memory = system.used_memory();
|
||||||
|
|
||||||
|
if total_memory > 0 {
|
||||||
|
Some((used_memory as f64 / total_memory as f64) * 100.0)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助函数:获取磁盘使用率
|
||||||
|
fn get_disk_usage() -> Option<f64> {
|
||||||
|
use sysinfo::Disks;
|
||||||
|
|
||||||
|
let disks = Disks::new_with_refreshed_list();
|
||||||
|
|
||||||
|
// 获取主磁盘的使用率
|
||||||
|
if let Some(disk) = disks.iter().next() {
|
||||||
|
let total_space = disk.total_space();
|
||||||
|
let available_space = disk.available_space();
|
||||||
|
let used_space = total_space - available_space;
|
||||||
|
|
||||||
|
if total_space > 0 {
|
||||||
|
Some((used_space as f64 / total_space as f64) * 100.0)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助函数:计算每分钟请求数
|
||||||
|
fn calculate_requests_per_minute(stats: &crate::data::repositories::workflow_execution_record_repository::ExecutionStatistics) -> u32 {
|
||||||
|
// 基于今天的总执行数估算每分钟请求数
|
||||||
|
let total_today = stats.total_executions;
|
||||||
|
let hours_passed = chrono::Utc::now().hour() + 1; // 至少1小时
|
||||||
|
let minutes_passed = hours_passed * 60;
|
||||||
|
|
||||||
|
if minutes_passed > 0 {
|
||||||
|
(total_today * 60) / minutes_passed
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助函数:获取系统运行时间
|
||||||
|
fn get_uptime_hours() -> f64 {
|
||||||
|
use sysinfo::System;
|
||||||
|
|
||||||
|
System::uptime() as f64 / 3600.0 // 转换为小时
|
||||||
|
}
|
||||||
|
|||||||
@@ -146,6 +146,8 @@ export const EnvironmentConfigurator: React.FC<EnvironmentConfiguratorProps> = (
|
|||||||
// 初始化表单数据
|
// 初始化表单数据
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (environment) {
|
if (environment) {
|
||||||
|
console.log('EnvironmentConfigurator 接收到环境数据:', environment);
|
||||||
|
console.log('环境类型:', environment.environment_type, '类型:', typeof environment.environment_type);
|
||||||
setFormData({
|
setFormData({
|
||||||
name: environment.name,
|
name: environment.name,
|
||||||
environment_type: environment.environment_type,
|
environment_type: environment.environment_type,
|
||||||
@@ -159,6 +161,7 @@ export const EnvironmentConfigurator: React.FC<EnvironmentConfiguratorProps> = (
|
|||||||
max_execution_time_seconds: environment.max_execution_time_seconds,
|
max_execution_time_seconds: environment.max_execution_time_seconds,
|
||||||
tags: environment.tags || []
|
tags: environment.tags || []
|
||||||
});
|
});
|
||||||
|
console.log('设置的表单数据 environment_type:', environment.environment_type);
|
||||||
} else {
|
} else {
|
||||||
// 重置为默认值
|
// 重置为默认值
|
||||||
setFormData({
|
setFormData({
|
||||||
|
|||||||
@@ -53,6 +53,15 @@ interface WorkflowExecutionRecord {
|
|||||||
updated_at: string;
|
updated_at: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 执行历史分页响应接口
|
||||||
|
interface ExecutionHistoryResponse {
|
||||||
|
records: WorkflowExecutionRecord[];
|
||||||
|
total_count: number;
|
||||||
|
page: number;
|
||||||
|
page_size: number;
|
||||||
|
total_pages: number;
|
||||||
|
}
|
||||||
|
|
||||||
// 筛选器接口
|
// 筛选器接口
|
||||||
interface ExecutionRecordFilter {
|
interface ExecutionRecordFilter {
|
||||||
workflow_template_id?: number;
|
workflow_template_id?: number;
|
||||||
@@ -136,16 +145,14 @@ export const ExecutionHistoryList: React.FC<ExecutionHistoryListProps> = ({
|
|||||||
filterConditions.date_from = dateFrom.toISOString();
|
filterConditions.date_from = dateFrom.toISOString();
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await invoke<WorkflowExecutionRecord[]>('get_execution_history', {
|
const result = await invoke<ExecutionHistoryResponse>('get_execution_history', {
|
||||||
filter: filterConditions,
|
filter: filterConditions,
|
||||||
limit: pageSize,
|
limit: pageSize,
|
||||||
offset: (currentPage - 1) * pageSize
|
offset: (currentPage - 1) * pageSize
|
||||||
});
|
});
|
||||||
|
|
||||||
setRecords(result);
|
setRecords(result.records);
|
||||||
|
setTotalPages(result.total_pages);
|
||||||
// TODO: 获取总数来计算总页数
|
|
||||||
setTotalPages(Math.ceil(result.length / pageSize));
|
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('加载执行历史失败:', err);
|
console.error('加载执行历史失败:', err);
|
||||||
|
|||||||
@@ -40,6 +40,15 @@ interface WorkflowExecutionRecord {
|
|||||||
updated_at: string;
|
updated_at: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 执行历史分页响应接口
|
||||||
|
interface ExecutionHistoryResponse {
|
||||||
|
records: WorkflowExecutionRecord[];
|
||||||
|
total_count: number;
|
||||||
|
page: number;
|
||||||
|
page_size: number;
|
||||||
|
total_pages: number;
|
||||||
|
}
|
||||||
|
|
||||||
// 系统统计信息接口
|
// 系统统计信息接口
|
||||||
interface SystemStatistics {
|
interface SystemStatistics {
|
||||||
execution_stats: {
|
execution_stats: {
|
||||||
@@ -128,24 +137,24 @@ export const MonitoringDashboard: React.FC<MonitoringDashboardProps> = ({
|
|||||||
// 加载活跃执行
|
// 加载活跃执行
|
||||||
const loadActiveExecutions = useCallback(async () => {
|
const loadActiveExecutions = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
const result = await invoke<WorkflowExecutionRecord[]>('get_execution_history', {
|
const result = await invoke<ExecutionHistoryResponse>('get_execution_history', {
|
||||||
filter: {
|
filter: {
|
||||||
status: 'running' // 只获取正在执行的
|
status: 'running' // 只获取正在执行的
|
||||||
},
|
},
|
||||||
limit: 50,
|
limit: 50,
|
||||||
offset: 0
|
offset: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
// 同时获取等待中的执行
|
// 同时获取等待中的执行
|
||||||
const pendingResult = await invoke<WorkflowExecutionRecord[]>('get_execution_history', {
|
const pendingResult = await invoke<ExecutionHistoryResponse>('get_execution_history', {
|
||||||
filter: {
|
filter: {
|
||||||
status: 'pending'
|
status: 'pending'
|
||||||
},
|
},
|
||||||
limit: 50,
|
limit: 50,
|
||||||
offset: 0
|
offset: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
setActiveExecutions([...result, ...pendingResult]);
|
setActiveExecutions([...result.records, ...pendingResult.records]);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('加载活跃执行失败:', err);
|
console.error('加载活跃执行失败:', err);
|
||||||
// 使用模拟数据
|
// 使用模拟数据
|
||||||
@@ -156,45 +165,44 @@ export const MonitoringDashboard: React.FC<MonitoringDashboardProps> = ({
|
|||||||
// 加载系统统计
|
// 加载系统统计
|
||||||
const loadSystemStats = useCallback(async () => {
|
const loadSystemStats = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
// TODO: 实现实际的系统统计API
|
const result = await invoke<SystemStatistics>('get_system_statistics');
|
||||||
// const result = await invoke<SystemStatistics>('get_system_statistics');
|
setSystemStats(result);
|
||||||
// setSystemStats(result);
|
} catch (err) {
|
||||||
|
console.error('加载系统统计失败:', err);
|
||||||
// 暂时使用模拟数据
|
|
||||||
const mockStats: SystemStatistics = {
|
// 如果API调用失败,使用基础的模拟数据作为后备
|
||||||
|
const fallbackStats: SystemStatistics = {
|
||||||
execution_stats: {
|
execution_stats: {
|
||||||
total_executions_today: 156,
|
total_executions_today: 0,
|
||||||
successful_executions_today: 142,
|
successful_executions_today: 0,
|
||||||
failed_executions_today: 14,
|
failed_executions_today: 0,
|
||||||
average_execution_time_seconds: 45.6,
|
average_execution_time_seconds: 0,
|
||||||
current_queue_size: activeExecutions.filter(e => e.status === 'pending').length,
|
current_queue_size: activeExecutions.filter(e => e.status === 'pending').length,
|
||||||
active_executions: activeExecutions.filter(e => e.status === 'running').length
|
active_executions: activeExecutions.filter(e => e.status === 'running').length
|
||||||
},
|
},
|
||||||
environment_stats: {
|
environment_stats: {
|
||||||
total_environments: 3,
|
total_environments: 0,
|
||||||
healthy_environments: 2,
|
healthy_environments: 0,
|
||||||
unhealthy_environments: 1,
|
unhealthy_environments: 0,
|
||||||
average_response_time_ms: 1250,
|
average_response_time_ms: 0,
|
||||||
total_capacity: 16,
|
total_capacity: 0,
|
||||||
used_capacity: activeExecutions.filter(e => e.status === 'running').length
|
used_capacity: activeExecutions.filter(e => e.status === 'running').length
|
||||||
},
|
},
|
||||||
system_resources: {
|
system_resources: {
|
||||||
cpu_usage_percent: Math.random() * 30 + 20, // 20-50%
|
cpu_usage_percent: 0,
|
||||||
memory_usage_percent: Math.random() * 20 + 40, // 40-60%
|
memory_usage_percent: 0,
|
||||||
disk_usage_percent: Math.random() * 10 + 65, // 65-75%
|
disk_usage_percent: 0,
|
||||||
network_status: 'connected'
|
network_status: 'disconnected'
|
||||||
},
|
},
|
||||||
performance_metrics: {
|
performance_metrics: {
|
||||||
requests_per_minute: 24,
|
requests_per_minute: 0,
|
||||||
average_response_time_ms: 1250,
|
average_response_time_ms: 0,
|
||||||
error_rate_percent: 8.97,
|
error_rate_percent: 0,
|
||||||
uptime_hours: 72.5
|
uptime_hours: 0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
setSystemStats(mockStats);
|
setSystemStats(fallbackStats);
|
||||||
} catch (err) {
|
|
||||||
console.error('加载系统统计失败:', err);
|
|
||||||
}
|
}
|
||||||
}, [activeExecutions]);
|
}, [activeExecutions]);
|
||||||
|
|
||||||
|
|||||||
@@ -144,50 +144,108 @@ export const WorkflowPage: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleEditEnvironment = (env: WorkflowExecutionEnvironment) => {
|
const handleEditEnvironment = (env: WorkflowExecutionEnvironment) => {
|
||||||
|
console.log('编辑环境,接收到的数据:', env);
|
||||||
|
console.log('环境类型:', env.environment_type, '类型:', typeof env.environment_type);
|
||||||
setSelectedEnvironment(env);
|
setSelectedEnvironment(env);
|
||||||
setIsEnvironmentConfiguratorOpen(true);
|
setIsEnvironmentConfiguratorOpen(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteEnvironment = async (envId: number) => {
|
const handleDeleteEnvironment = async (envId: number) => {
|
||||||
try {
|
try {
|
||||||
// TODO: 实现删除逻辑
|
// 确认删除
|
||||||
|
const confirmed = window.confirm('确定要删除这个执行环境吗?此操作不可撤销。');
|
||||||
|
if (!confirmed) return;
|
||||||
|
|
||||||
console.log('删除执行环境:', envId);
|
console.log('删除执行环境:', envId);
|
||||||
|
await invoke('delete_execution_environment', { id: envId });
|
||||||
|
|
||||||
|
console.log('环境删除成功');
|
||||||
|
// 刷新页面以显示最新数据
|
||||||
|
window.location.reload();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('删除环境失败:', error);
|
console.error('删除环境失败:', error);
|
||||||
|
alert(`删除环境失败: ${error}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleHealthCheckEnvironment = async (envId: number) => {
|
const handleHealthCheckEnvironment = async (envId: number) => {
|
||||||
try {
|
try {
|
||||||
// TODO: 实现健康检查逻辑
|
|
||||||
console.log('健康检查环境:', envId);
|
console.log('健康检查环境:', envId);
|
||||||
|
// 调用健康检查命令
|
||||||
|
const healthStatus = await invoke('health_check_execution_environment', { id: envId });
|
||||||
|
console.log('健康检查完成,状态:', healthStatus);
|
||||||
|
|
||||||
|
// 刷新页面以显示最新的健康状态
|
||||||
|
window.location.reload();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('健康检查失败:', error);
|
console.error('健康检查失败:', error);
|
||||||
|
alert(`健康检查失败: ${error}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleToggleEnvironmentActive = async (envId: number, isActive: boolean) => {
|
const handleToggleEnvironmentActive = async (envId: number, isActive: boolean) => {
|
||||||
try {
|
try {
|
||||||
// TODO: 实现激活状态切换逻辑
|
|
||||||
console.log('切换环境激活状态:', envId, isActive);
|
console.log('切换环境激活状态:', envId, isActive);
|
||||||
|
const updatedEnvironment = await invoke('update_execution_environment', {
|
||||||
|
id: envId,
|
||||||
|
request: {
|
||||||
|
is_active: isActive
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log('激活状态切换成功:', updatedEnvironment);
|
||||||
|
|
||||||
|
// 刷新页面以显示最新状态
|
||||||
|
window.location.reload();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('切换激活状态失败:', error);
|
console.error('切换激活状态失败:', error);
|
||||||
|
alert(`切换激活状态失败: ${error}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSaveEnvironment = async (envData: CreateEnvironmentRequest) => {
|
const handleSaveEnvironment = async (envData: CreateEnvironmentRequest) => {
|
||||||
try {
|
try {
|
||||||
if (selectedEnvironment) {
|
if (selectedEnvironment) {
|
||||||
// TODO: 实现更新逻辑
|
// 更新现有环境 - 简化逻辑,直接传递所有字段
|
||||||
console.log('更新环境:', envData);
|
console.log('更新环境:', envData);
|
||||||
|
const updateRequest = {
|
||||||
|
name: envData.name,
|
||||||
|
description: envData.description,
|
||||||
|
base_url: envData.base_url,
|
||||||
|
api_key: envData.api_key,
|
||||||
|
connection_config_json: envData.connection_config_json,
|
||||||
|
supported_workflow_types: envData.supported_workflow_types,
|
||||||
|
max_concurrent_jobs: envData.max_concurrent_jobs,
|
||||||
|
priority: envData.priority,
|
||||||
|
max_memory_mb: envData.max_memory_mb,
|
||||||
|
max_execution_time_seconds: envData.max_execution_time_seconds,
|
||||||
|
metadata_json: envData.metadata_json,
|
||||||
|
tags: envData.tags,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log('发送更新请求:', updateRequest);
|
||||||
|
const updatedEnvironment = await invoke('update_execution_environment', {
|
||||||
|
id: selectedEnvironment.id,
|
||||||
|
request: updateRequest
|
||||||
|
});
|
||||||
|
console.log('更新成功,返回数据:', updatedEnvironment);
|
||||||
} else {
|
} else {
|
||||||
// TODO: 实现创建逻辑
|
// 创建新环境
|
||||||
console.log('创建环境:', envData);
|
console.log('创建环境:', envData);
|
||||||
|
await invoke('create_execution_environment', { request: envData });
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsEnvironmentConfiguratorOpen(false);
|
setIsEnvironmentConfiguratorOpen(false);
|
||||||
setSelectedEnvironment(null);
|
setSelectedEnvironment(null);
|
||||||
|
|
||||||
|
// TODO: 添加成功提示
|
||||||
|
console.log('环境保存成功');
|
||||||
|
|
||||||
|
// 刷新页面以显示最新数据(临时方案)
|
||||||
|
window.location.reload();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('保存环境失败:', error);
|
console.error('保存环境失败:', error);
|
||||||
|
// TODO: 添加错误提示UI
|
||||||
|
alert(`保存环境失败: ${error}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -161,6 +161,15 @@ export interface WorkflowExecutionRecord {
|
|||||||
updated_at: string;
|
updated_at: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 执行历史分页响应接口
|
||||||
|
export interface ExecutionHistoryResponse {
|
||||||
|
records: WorkflowExecutionRecord[];
|
||||||
|
total_count: number;
|
||||||
|
page: number;
|
||||||
|
page_size: number;
|
||||||
|
total_pages: number;
|
||||||
|
}
|
||||||
|
|
||||||
// 执行环境接口
|
// 执行环境接口
|
||||||
export interface WorkflowExecutionEnvironment {
|
export interface WorkflowExecutionEnvironment {
|
||||||
id: number;
|
id: number;
|
||||||
|
|||||||
Reference in New Issue
Block a user