fix: 重构App结构体,settings数据持久化到App中

This commit is contained in:
xiaji
2026-04-13 22:43:55 +08:00
parent 21103bdf9f
commit c6c92d31ec

View File

@@ -51,7 +51,6 @@ impl Config {
} }
} }
// 尝试从环境变量加载
dotenv().ok(); dotenv().ok();
Self { Self {
host: env::var("PROXMOX_HOST").unwrap_or_default(), host: env::var("PROXMOX_HOST").unwrap_or_default(),
@@ -91,17 +90,10 @@ pub struct AppState {
pub vm_status: String, pub vm_status: String,
pub log_buffer: Vec<String>, pub log_buffer: Vec<String>,
pub is_connected: bool, pub is_connected: bool,
pub host: String,
pub port: u16,
pub show_settings: bool,
pub token_id: String,
pub token_secret: String,
} }
impl AppState { impl AppState {
pub fn new() -> Self { pub fn new(config: &Config) -> Self {
let config = Config::load();
let client = if !config.host.is_empty() && !config.token_id.is_empty() && !config.token_secret.is_empty() { let client = if !config.host.is_empty() && !config.token_id.is_empty() && !config.token_secret.is_empty() {
let c = ProxmoxClient::new(&config.host, config.port, &config.token_id, &config.token_secret); let c = ProxmoxClient::new(&config.host, config.port, &config.token_id, &config.token_secret);
Arc::new(Mutex::new(Some(c))) Arc::new(Mutex::new(Some(c)))
@@ -114,15 +106,10 @@ impl AppState {
Self { Self {
client, client,
vm_id: config.vm_id, vm_id: config.vm_id,
node: config.node, node: config.node.clone(),
vm_status: "未知".to_string(), vm_status: "未知".to_string(),
log_buffer: vec!["程序启动".to_string()], log_buffer: vec!["程序启动".to_string()],
is_connected, is_connected,
host: config.host,
port: config.port,
show_settings: false,
token_id: config.token_id,
token_secret: config.token_secret,
} }
} }
@@ -133,18 +120,13 @@ impl AppState {
self.log_buffer.remove(0); self.log_buffer.remove(0);
} }
} }
}
pub fn save_config(&self) { pub struct SettingsData {
let config = Config { pub host: String,
host: self.host.clone(), pub port: u16,
port: self.port, pub token_id: String,
token_id: self.token_id.clone(), pub token_secret: String,
token_secret: self.token_secret.clone(),
vm_id: self.vm_id,
node: self.node.clone(),
};
config.save();
}
} }
pub fn gui_run() { pub fn gui_run() {
@@ -178,12 +160,24 @@ pub fn gui_run() {
struct App { struct App {
state: SharedState, state: SharedState,
show_settings: bool,
settings: SettingsData,
} }
impl App { impl App {
fn new() -> Self { fn new() -> Self {
let config = Config::load();
let settings = SettingsData {
host: config.host.clone(),
port: config.port,
token_id: config.token_id.clone(),
token_secret: config.token_secret.clone(),
};
Self { Self {
state: Arc::new(RwLock::new(AppState::new())), state: Arc::new(RwLock::new(AppState::new(&config))),
show_settings: false,
settings,
} }
} }
} }
@@ -191,7 +185,6 @@ impl App {
impl eframe::App for App { impl eframe::App for App {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
let state = self.state.clone(); let state = self.state.clone();
let ctx_clone = ctx.clone();
egui::CentralPanel::default().show(ctx, |ui| { egui::CentralPanel::default().show(ctx, |ui| {
// 标题栏 // 标题栏
@@ -199,7 +192,7 @@ impl eframe::App for App {
ui.heading("Proxmox VM 控制器"); ui.heading("Proxmox VM 控制器");
ui.with_layout(egui::Layout::right_to_left(egui::Align::Min), |ui| { ui.with_layout(egui::Layout::right_to_left(egui::Align::Min), |ui| {
if ui.button("⚙ 设置").clicked() { if ui.button("⚙ 设置").clicked() {
state.write().unwrap().show_settings = true; self.show_settings = true;
} }
}); });
}); });
@@ -345,12 +338,9 @@ impl eframe::App for App {
ctx.request_repaint(); ctx.request_repaint();
thread::spawn(move || { thread::spawn(move || {
let rt = tokio::runtime::Runtime::new().unwrap(); let rt = tokio::runtime::Runtime::new().unwrap();
// 先停止所有运行的虚拟机
let _ = rt.block_on(async { let _ = rt.block_on(async {
// 获取节点上所有虚拟机
let client = client.lock().unwrap(); let client = client.lock().unwrap();
if let Some(c) = client.as_ref() { if let Some(c) = client.as_ref() {
// 发送关闭节点命令
c.shutdown_node(&node).await.ok(); c.shutdown_node(&node).await.ok();
} }
}); });
@@ -376,17 +366,10 @@ impl eframe::App for App {
}); });
}); });
// 设置窗口
let show_settings = st.show_settings;
let state_clone = state.clone();
let mut st_host = st.host.clone();
let mut st_port = st.port;
let mut st_token_id = st.token_id.clone();
let mut st_token_secret = st.token_secret.clone();
drop(st); drop(st);
if show_settings { // 设置窗口
if self.show_settings {
egui::Window::new("设置") egui::Window::new("设置")
.collapsible(false) .collapsible(false)
.resizable(false) .resizable(false)
@@ -401,59 +384,68 @@ impl eframe::App for App {
// Base URL 显示 // Base URL 显示
ui.label("API 地址:"); ui.label("API 地址:");
ui.colored_label(egui::Color32::GRAY, format!("https://{}:{}/api2/json/", st_host, st_port)); ui.colored_label(egui::Color32::GRAY, format!("https://{}:{}/api2/json/", self.settings.host, self.settings.port));
ui.add_space(8.0); ui.add_space(8.0);
// Host 输入 // Host 输入
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.label("Host:"); ui.label("Host:");
ui.add(egui::TextEdit::singleline(&mut st_host).desired_width(200.0)); ui.add(egui::TextEdit::singleline(&mut self.settings.host).desired_width(200.0));
}); });
// Port 输入 // Port 输入
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.label("端口:"); ui.label("端口:");
ui.add(egui::DragValue::new(&mut st_port).range(1..=65535).speed(1)); ui.add(egui::DragValue::new(&mut self.settings.port).range(1..=65535).speed(1));
}); });
// 令牌ID 输入 // 令牌ID 输入
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.label("令牌ID:"); ui.label("令牌ID:");
ui.add(egui::TextEdit::singleline(&mut st_token_id).desired_width(200.0)); ui.add(egui::TextEdit::singleline(&mut self.settings.token_id).desired_width(200.0));
}); });
// 密钥 输入(密码框) // 密钥 输入(密码框)
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.label("密钥:"); ui.label("密钥:");
ui.add(egui::TextEdit::singleline(&mut st_token_secret).password(true).desired_width(200.0)); ui.add(egui::TextEdit::singleline(&mut self.settings.token_secret).password(true).desired_width(200.0));
}); });
ui.add_space(12.0); ui.add_space(12.0);
// 按钮 // 按钮
ui.horizontal(|ui| { ui.horizontal(|ui| {
let save_clicked = ui.button("💾 保存").clicked(); if ui.button("💾 保存").clicked() {
let cancel_clicked = ui.button("取消").clicked(); if !self.settings.host.is_empty() && !self.settings.token_id.is_empty() && !self.settings.token_secret.is_empty() {
let client = ProxmoxClient::new(
&self.settings.host,
self.settings.port,
&self.settings.token_id,
&self.settings.token_secret
);
if save_clicked { let config = Config {
if !st_host.is_empty() && !st_token_id.is_empty() && !st_token_secret.is_empty() { host: self.settings.host.clone(),
let client = ProxmoxClient::new(&st_host, st_port, &st_token_id, &st_token_secret); port: self.settings.port,
let mut state = state_clone.write().unwrap(); token_id: self.settings.token_id.clone(),
state.host = st_host; token_secret: self.settings.token_secret.clone(),
state.port = st_port; vm_id: state.read().unwrap().vm_id,
state.token_id = st_token_id; node: state.read().unwrap().node.clone(),
state.token_secret = st_token_secret; };
state.client = Arc::new(Mutex::new(Some(client))); config.save();
state.is_connected = true;
state.save_config(); let mut st = state.write().unwrap();
state.add_log("配置已保存"); st.client = Arc::new(Mutex::new(Some(client)));
state.show_settings = false; st.is_connected = true;
st.add_log("配置已保存");
self.show_settings = false;
} }
} }
if cancel_clicked { if ui.button("取消").clicked() {
state_clone.write().unwrap().show_settings = false; self.show_settings = false;
} }
}); });