fix: 修复配置页面无法输入 + 添加关机按钮
This commit is contained in:
16
src/api.rs
16
src/api.rs
@@ -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(())
|
||||
}
|
||||
}
|
||||
52
src/gui.rs
52
src/gui.rs
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user