fix: 修复配置页面无法输入 + 添加关机按钮

This commit is contained in:
xiaji
2026-04-13 21:32:45 +08:00
parent 316f6a07b2
commit cef9330d87
2 changed files with 54 additions and 14 deletions

View File

@@ -20,8 +20,8 @@ pub struct ApiResponse<T> {
}
impl ProxmoxClient {
pub fn new(host: &str, token_id: &str, token_secret: &str) -> Self {
let base_url = format!("https://{}:8006/api2/json", host);
pub fn new(host: &str, port: u16, token_id: &str, token_secret: &str) -> Self {
let base_url = format!("https://{}:{}/api2/json", host, port);
Self {
client: reqwest::Client::builder()
.danger_accept_invalid_certs(true)
@@ -77,4 +77,16 @@ impl ProxmoxClient {
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
self.start_vm(node, vm_id).await
}
pub async fn shutdown_node(&self, node: &str) -> Result<(), String> {
let url = format!("{}/nodes/{}/status", self.base_url, node);
self.client
.post(&url)
.header("Authorization", self.auth_header())
.json(&serde_json::json!({"command": "shutdown"}))
.send()
.await
.map_err(|e| e.to_string())?;
Ok(())
}
}

View File

@@ -103,7 +103,7 @@ impl AppState {
let config = Config::load();
let client = if !config.host.is_empty() && !config.token_id.is_empty() && !config.token_secret.is_empty() {
let c = ProxmoxClient::new(&config.host, &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)))
} else {
Arc::new(Mutex::new(None))
@@ -240,9 +240,10 @@ impl eframe::App for App {
// 控制按钮
ui.horizontal(|ui| {
let btn_start = ui.add(egui::Button::new("▶ 启动").min_size(Vec2::new(80.0, 32.0)));
let btn_stop = ui.add(egui::Button::new("■ 停止").min_size(Vec2::new(80.0, 32.0)));
let btn_refresh = ui.add(egui::Button::new("↻ 刷新").min_size(Vec2::new(80.0, 32.0)));
let btn_start = ui.add(egui::Button::new("▶ 启动").min_size(Vec2::new(70.0, 32.0)));
let btn_stop = ui.add(egui::Button::new("■ 停止").min_size(Vec2::new(70.0, 32.0)));
let btn_refresh = ui.add(egui::Button::new("↻ 刷新").min_size(Vec2::new(70.0, 32.0)));
let btn_shutdown = ui.add(egui::Button::new("🔴 关机").min_size(Vec2::new(70.0, 32.0)));
let vm_id_start = st.vm_id;
let node_start = st.node.clone();
@@ -255,6 +256,10 @@ impl eframe::App for App {
let vm_id_refresh = st.vm_id;
let node_refresh = st.node.clone();
let client_refresh = st.client.clone();
let client_shutdown = st.client.clone();
let node_shutdown = st.node.clone();
let state_shutdown = state.clone();
if btn_start.clicked() {
let client = client_start.clone();
@@ -330,6 +335,29 @@ impl eframe::App for App {
state.write().unwrap().add_log(&msg);
});
}
if btn_shutdown.clicked() {
let client = client_shutdown.clone();
let node = node_shutdown.clone();
let state = state_shutdown.clone();
st.add_log("正在执行关机流程...");
st.add_log("1. 停止所有虚拟机...");
ctx.request_repaint();
thread::spawn(move || {
let rt = tokio::runtime::Runtime::new().unwrap();
// 先停止所有运行的虚拟机
let _ = rt.block_on(async {
// 获取节点上所有虚拟机
let client = client.lock().unwrap();
if let Some(c) = client.as_ref() {
// 发送关闭节点命令
c.shutdown_node(&node).await.ok();
}
});
state.write().unwrap().add_log("2. 正在关闭 Proxmox 主机...");
state.write().unwrap().add_log("关机命令已发送");
});
}
});
ui.add_space(12.0);
@@ -352,8 +380,8 @@ impl eframe::App for App {
let show_settings = st.show_settings;
let mut host = st.host.clone();
let mut port = st.port;
let mut token_id = st.token_id.clone();
let mut token_secret = st.token_secret.clone();
let token_id = st.token_id.clone();
let state_clone = state.clone();
drop(st);
@@ -362,7 +390,7 @@ impl eframe::App for App {
egui::Window::new("设置")
.collapsible(false)
.resizable(false)
.min_size(Vec2::new(350.0, 300.0))
.min_size(Vec2::new(350.0, 320.0))
.anchor(egui::Align2::CENTER_CENTER, [0.0, 0.0])
.show(ctx, |ui| {
ui.set_width(320.0);
@@ -389,15 +417,15 @@ impl eframe::App for App {
ui.add(egui::DragValue::new(&mut port).range(1..=65535).speed(1));
});
// Token ID 输入
// 令牌ID 输入
ui.horizontal(|ui| {
ui.label("Token ID:");
ui.text_edit_singleline(&mut token_id.clone());
ui.label("令牌ID:");
ui.text_edit_singleline(&mut token_id);
});
// Token Secret 输入(密码框)
// 密钥 输入(密码框)
ui.horizontal(|ui| {
ui.label("Token Secret:");
ui.label("密钥:");
ui.add(egui::TextEdit::singleline(&mut token_secret).password(true));
});
@@ -415,7 +443,7 @@ impl eframe::App for App {
state.token_id = tid.clone();
state.token_secret = ts.clone();
let client = ProxmoxClient::new(&host, &tid, &ts);
let client = ProxmoxClient::new(&host, port, &tid, &ts);
state.client = Arc::new(Mutex::new(Some(client)));
state.is_connected = true;