新增多个核心功能模块(后端 Rust 命令 + 前端 Panel 全部接线完成): - 服务器注册表:servers.rs + ServerManagerPanel、ProjectServerPanel(项目关联服务器) - SSH Config 自动同步:ssh_config.rs - 服务器软件管理:server_software.rs + ServerSoftwareBlock - 宿主机应用管理:host_apps.rs + HostAppsPanel - 服务配置管理:service_config.rs + ServiceConfigBlock - 项目部署信息:deploy_info.rs + DeployInfoPanel - API密钥管理:api_keys.rs + ApiKeysPanel - 云产品管理:cloud_products.rs + CloudProductsPanel(含 Docker应用、云数据库实例子模块) - 源码库:source_library.rs + SourceLibraryPage(分类管理 + 项目详情) 导航栏新增「源码库」入口;蓝图 manifest 同步补录 7 个新模块
112 lines
3.8 KiB
Rust
112 lines
3.8 KiB
Rust
use rusqlite::{params, Connection};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
|
pub struct DockerApp {
|
|
pub id: String,
|
|
pub product_id: String,
|
|
pub name: String,
|
|
pub access_url: Option<String>,
|
|
pub username: Option<String>,
|
|
pub password: Option<String>,
|
|
pub notes: Option<String>,
|
|
pub sort_order: i32,
|
|
pub created_at: Option<String>,
|
|
pub updated_at: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct SaveDockerAppInput {
|
|
pub product_id: String,
|
|
pub name: String,
|
|
pub access_url: Option<String>,
|
|
pub username: Option<String>,
|
|
pub password: Option<String>,
|
|
pub notes: Option<String>,
|
|
pub sort_order: Option<i32>,
|
|
}
|
|
|
|
const COLS: &str =
|
|
"id, product_id, name, access_url, username, password, notes, sort_order, created_at, updated_at";
|
|
|
|
fn row_to_app(row: &rusqlite::Row<'_>) -> rusqlite::Result<DockerApp> {
|
|
Ok(DockerApp {
|
|
id: row.get(0)?,
|
|
product_id: row.get(1)?,
|
|
name: row.get(2)?,
|
|
access_url: row.get(3)?,
|
|
username: row.get(4)?,
|
|
password: row.get(5)?,
|
|
notes: row.get(6)?,
|
|
sort_order: row.get(7)?,
|
|
created_at: row.get(8)?,
|
|
updated_at: row.get(9)?,
|
|
})
|
|
}
|
|
|
|
fn get_by_id(conn: &Connection, id: &str) -> Option<DockerApp> {
|
|
let sql = format!("SELECT {COLS} FROM docker_apps WHERE id = ?1");
|
|
conn.query_row(&sql, params![id], row_to_app).ok()
|
|
}
|
|
|
|
// ── Tauri commands ───────────────────────────────────────────────────────────
|
|
|
|
#[tauri::command]
|
|
pub fn get_docker_apps(product_id: String) -> Result<Vec<DockerApp>, String> {
|
|
let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
|
|
let sql = format!(
|
|
"SELECT {COLS} FROM docker_apps WHERE product_id = ?1 ORDER BY sort_order, name"
|
|
);
|
|
let mut stmt = conn.prepare(&sql).map_err(|e| e.to_string())?;
|
|
let rows = stmt
|
|
.query_map(params![product_id], row_to_app)
|
|
.map_err(|e| e.to_string())?
|
|
.filter_map(|r| r.ok())
|
|
.collect();
|
|
Ok(rows)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn add_docker_app(input: SaveDockerAppInput) -> Result<DockerApp, String> {
|
|
let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
|
|
let id = format!("dapp-{}", uuid::Uuid::new_v4());
|
|
conn.execute(
|
|
"INSERT INTO docker_apps
|
|
(id, product_id, name, access_url, username, password, notes, sort_order)
|
|
VALUES (?1,?2,?3,?4,?5,?6,?7,?8)",
|
|
params![
|
|
id, input.product_id, input.name,
|
|
input.access_url, input.username, input.password,
|
|
input.notes, input.sort_order.unwrap_or(0)
|
|
],
|
|
)
|
|
.map_err(|e| e.to_string())?;
|
|
get_by_id(&conn, &id).ok_or_else(|| "创建后查询失败".into())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn edit_docker_app(id: String, input: SaveDockerAppInput) -> Result<DockerApp, String> {
|
|
let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
|
|
let rows = conn.execute(
|
|
"UPDATE docker_apps
|
|
SET name=?1, access_url=?2, username=?3, password=?4,
|
|
notes=?5, sort_order=?6, updated_at=datetime('now')
|
|
WHERE id=?7",
|
|
params![
|
|
input.name, input.access_url, input.username, input.password,
|
|
input.notes, input.sort_order.unwrap_or(0), id
|
|
],
|
|
)
|
|
.map_err(|e| e.to_string())?;
|
|
if rows == 0 { return Err(format!("应用 {} 不存在", id)); }
|
|
get_by_id(&conn, &id).ok_or_else(|| "更新后查询失败".into())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn delete_docker_app(id: String) -> Result<(), String> {
|
|
let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
|
|
conn.execute("DELETE FROM docker_apps WHERE id=?1", params![id])
|
|
.map_err(|e| e.to_string())?;
|
|
Ok(())
|
|
}
|