172 lines
6.0 KiB
Rust
172 lines
6.0 KiB
Rust
use rusqlite::{params, Connection};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
|
pub struct HostApp {
|
|
pub id: String,
|
|
pub server_id: String,
|
|
pub name: String,
|
|
pub deploy_type: String,
|
|
pub service_name: Option<String>,
|
|
pub binary_path: Option<String>,
|
|
pub config_path: Option<String>,
|
|
pub log_path: Option<String>,
|
|
pub port: Option<String>,
|
|
pub start_cmd: Option<String>,
|
|
pub stop_cmd: Option<String>,
|
|
pub restart_cmd: Option<String>,
|
|
pub status_cmd: Option<String>,
|
|
pub notes: Option<String>,
|
|
pub sort_order: Option<i32>,
|
|
pub created_at: Option<String>,
|
|
pub updated_at: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct SaveHostAppInput {
|
|
pub name: String,
|
|
pub deploy_type: String,
|
|
pub service_name: Option<String>,
|
|
pub binary_path: Option<String>,
|
|
pub config_path: Option<String>,
|
|
pub log_path: Option<String>,
|
|
pub port: Option<String>,
|
|
pub start_cmd: Option<String>,
|
|
pub stop_cmd: Option<String>,
|
|
pub restart_cmd: Option<String>,
|
|
pub status_cmd: Option<String>,
|
|
pub notes: Option<String>,
|
|
pub sort_order: Option<i32>,
|
|
}
|
|
|
|
const COLS: &str = "id, server_id, name, deploy_type, service_name, binary_path, config_path, log_path, port, start_cmd, stop_cmd, restart_cmd, status_cmd, notes, sort_order, created_at, updated_at";
|
|
|
|
fn row_to_app(row: &rusqlite::Row<'_>) -> rusqlite::Result<HostApp> {
|
|
Ok(HostApp {
|
|
id: row.get(0)?,
|
|
server_id: row.get(1)?,
|
|
name: row.get(2)?,
|
|
deploy_type: row.get(3)?,
|
|
service_name: row.get(4)?,
|
|
binary_path: row.get(5)?,
|
|
config_path: row.get(6)?,
|
|
log_path: row.get(7)?,
|
|
port: row.get(8)?,
|
|
start_cmd: row.get(9)?,
|
|
stop_cmd: row.get(10)?,
|
|
restart_cmd: row.get(11)?,
|
|
status_cmd: row.get(12)?,
|
|
notes: row.get(13)?,
|
|
sort_order: row.get(14)?,
|
|
created_at: row.get(15)?,
|
|
updated_at: row.get(16)?,
|
|
})
|
|
}
|
|
|
|
pub fn list_host_apps(conn: &Connection, server_id: &str) -> Vec<HostApp> {
|
|
let sql = format!("SELECT {COLS} FROM server_host_apps WHERE server_id = ?1 ORDER BY sort_order ASC, created_at ASC");
|
|
let mut stmt = match conn.prepare(&sql) {
|
|
Ok(s) => s,
|
|
Err(_) => return vec![],
|
|
};
|
|
stmt.query_map(params![server_id], row_to_app)
|
|
.map(|iter| iter.filter_map(|r| r.ok()).collect())
|
|
.unwrap_or_default()
|
|
}
|
|
|
|
pub fn get_host_app(conn: &Connection, id: &str) -> Option<HostApp> {
|
|
let sql = format!("SELECT {COLS} FROM server_host_apps WHERE id = ?1");
|
|
conn.query_row(&sql, params![id], row_to_app).ok()
|
|
}
|
|
|
|
pub fn create_host_app(
|
|
conn: &Connection,
|
|
server_id: &str,
|
|
input: &SaveHostAppInput,
|
|
) -> Result<HostApp, String> {
|
|
let id = format!("ha-{}", uuid::Uuid::new_v4());
|
|
conn.execute(
|
|
"INSERT INTO server_host_apps (id, server_id, name, deploy_type, service_name, binary_path, config_path, log_path, port, start_cmd, stop_cmd, restart_cmd, status_cmd, notes, sort_order)
|
|
VALUES (?1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12,?13,?14,?15)",
|
|
params![id, server_id, input.name, input.deploy_type, input.service_name, input.binary_path,
|
|
input.config_path, input.log_path, input.port, input.start_cmd, input.stop_cmd,
|
|
input.restart_cmd, input.status_cmd, input.notes, input.sort_order.unwrap_or(0)],
|
|
).map_err(|e| e.to_string())?;
|
|
get_host_app(conn, &id).ok_or_else(|| "创建后查询失败".into())
|
|
}
|
|
|
|
pub fn update_host_app(
|
|
conn: &Connection,
|
|
id: &str,
|
|
input: &SaveHostAppInput,
|
|
) -> Result<HostApp, String> {
|
|
let rows = conn
|
|
.execute(
|
|
"UPDATE server_host_apps SET name=?1, deploy_type=?2, service_name=?3, binary_path=?4,
|
|
config_path=?5, log_path=?6, port=?7, start_cmd=?8, stop_cmd=?9, restart_cmd=?10,
|
|
status_cmd=?11, notes=?12, sort_order=?13, updated_at=datetime('now') WHERE id=?14",
|
|
params![
|
|
input.name,
|
|
input.deploy_type,
|
|
input.service_name,
|
|
input.binary_path,
|
|
input.config_path,
|
|
input.log_path,
|
|
input.port,
|
|
input.start_cmd,
|
|
input.stop_cmd,
|
|
input.restart_cmd,
|
|
input.status_cmd,
|
|
input.notes,
|
|
input.sort_order.unwrap_or(0),
|
|
id
|
|
],
|
|
)
|
|
.map_err(|e| e.to_string())?;
|
|
if rows == 0 {
|
|
return Err(format!("应用 {} 不存在", id));
|
|
}
|
|
get_host_app(conn, id).ok_or_else(|| "更新后查询失败".into())
|
|
}
|
|
|
|
pub fn delete_host_app_fn(conn: &Connection, id: &str) -> Result<(), String> {
|
|
conn.execute("DELETE FROM server_host_apps WHERE id=?1", params![id])
|
|
.map_err(|e| e.to_string())?;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn delete_apps_by_server(conn: &Connection, server_id: &str) -> Result<(), String> {
|
|
conn.execute(
|
|
"DELETE FROM server_host_apps WHERE server_id=?1",
|
|
params![server_id],
|
|
)
|
|
.map_err(|e| e.to_string())?;
|
|
Ok(())
|
|
}
|
|
|
|
// ── Tauri commands ───────────────────────────────────────────────────────────
|
|
|
|
#[tauri::command]
|
|
pub fn get_host_apps(server_id: String) -> Result<Vec<HostApp>, String> {
|
|
let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
|
|
Ok(list_host_apps(&conn, &server_id))
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn add_host_app(server_id: String, input: SaveHostAppInput) -> Result<HostApp, String> {
|
|
let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
|
|
create_host_app(&conn, &server_id, &input)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn edit_host_app(id: String, input: SaveHostAppInput) -> Result<HostApp, String> {
|
|
let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
|
|
update_host_app(&conn, &id, &input)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn delete_host_app(id: String) -> Result<(), String> {
|
|
let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
|
|
delete_host_app_fn(&conn, &id)
|
|
}
|