fix: 重构App结构体,settings数据持久化到App中
This commit is contained in:
120
src/gui.rs
120
src/gui.rs
@@ -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(
|
||||||
if save_clicked {
|
&self.settings.host,
|
||||||
if !st_host.is_empty() && !st_token_id.is_empty() && !st_token_secret.is_empty() {
|
self.settings.port,
|
||||||
let client = ProxmoxClient::new(&st_host, st_port, &st_token_id, &st_token_secret);
|
&self.settings.token_id,
|
||||||
let mut state = state_clone.write().unwrap();
|
&self.settings.token_secret
|
||||||
state.host = st_host;
|
);
|
||||||
state.port = st_port;
|
|
||||||
state.token_id = st_token_id;
|
let config = Config {
|
||||||
state.token_secret = st_token_secret;
|
host: self.settings.host.clone(),
|
||||||
state.client = Arc::new(Mutex::new(Some(client)));
|
port: self.settings.port,
|
||||||
state.is_connected = true;
|
token_id: self.settings.token_id.clone(),
|
||||||
state.save_config();
|
token_secret: self.settings.token_secret.clone(),
|
||||||
state.add_log("配置已保存");
|
vm_id: state.read().unwrap().vm_id,
|
||||||
state.show_settings = false;
|
node: state.read().unwrap().node.clone(),
|
||||||
|
};
|
||||||
|
config.save();
|
||||||
|
|
||||||
|
let mut st = state.write().unwrap();
|
||||||
|
st.client = Arc::new(Mutex::new(Some(client)));
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user