新增多个核心功能模块(后端 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 个新模块
111 lines
3.9 KiB
Rust
111 lines
3.9 KiB
Rust
use rusqlite::{params, Connection};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
|
pub struct ApiKey {
|
|
pub id: String,
|
|
pub name: String,
|
|
pub provider: String,
|
|
pub api_key: String,
|
|
pub base_url: Option<String>,
|
|
pub model: Option<String>,
|
|
pub notes: Option<String>,
|
|
pub created_at: Option<String>,
|
|
pub updated_at: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct SaveApiKeyInput {
|
|
pub name: String,
|
|
pub provider: String,
|
|
pub api_key: String,
|
|
pub base_url: Option<String>,
|
|
pub model: Option<String>,
|
|
pub notes: Option<String>,
|
|
}
|
|
|
|
fn row_to_api_key(row: &rusqlite::Row<'_>) -> rusqlite::Result<ApiKey> {
|
|
Ok(ApiKey {
|
|
id: row.get(0)?,
|
|
name: row.get(1)?,
|
|
provider: row.get(2)?,
|
|
api_key: row.get(3)?,
|
|
base_url: row.get(4)?,
|
|
model: row.get(5)?,
|
|
notes: row.get(6)?,
|
|
created_at: row.get(7)?,
|
|
updated_at: row.get(8)?,
|
|
})
|
|
}
|
|
|
|
const SELECT_COLS: &str = "id, name, provider, api_key, base_url, model, notes, created_at, updated_at";
|
|
|
|
pub fn list_api_keys(conn: &Connection) -> Vec<ApiKey> {
|
|
let sql = format!("SELECT {SELECT_COLS} FROM api_keys ORDER BY updated_at DESC");
|
|
let mut stmt = match conn.prepare(&sql) {
|
|
Ok(s) => s,
|
|
Err(_) => return vec![],
|
|
};
|
|
stmt.query_map([], row_to_api_key)
|
|
.map(|iter| iter.filter_map(|r| r.ok()).collect())
|
|
.unwrap_or_default()
|
|
}
|
|
|
|
pub fn create_api_key(conn: &Connection, input: &SaveApiKeyInput) -> Result<ApiKey, String> {
|
|
let id = format!("ak-{}", uuid::Uuid::new_v4());
|
|
conn.execute(
|
|
"INSERT INTO api_keys (id, name, provider, api_key, base_url, model, notes)
|
|
VALUES (?1,?2,?3,?4,?5,?6,?7)",
|
|
params![id, input.name, input.provider, input.api_key, input.base_url, input.model, input.notes],
|
|
)
|
|
.map_err(|e| e.to_string())?;
|
|
get_api_key(conn, &id).ok_or_else(|| "创建后查询失败".into())
|
|
}
|
|
|
|
pub fn get_api_key(conn: &Connection, id: &str) -> Option<ApiKey> {
|
|
let sql = format!("SELECT {SELECT_COLS} FROM api_keys WHERE id = ?1");
|
|
conn.query_row(&sql, params![id], row_to_api_key).ok()
|
|
}
|
|
|
|
pub fn update_api_key(conn: &Connection, id: &str, input: &SaveApiKeyInput) -> Result<ApiKey, String> {
|
|
let rows = conn.execute(
|
|
"UPDATE api_keys SET name=?1, provider=?2, api_key=?3, base_url=?4, model=?5, notes=?6, updated_at=datetime('now')
|
|
WHERE id=?7",
|
|
params![input.name, input.provider, input.api_key, input.base_url, input.model, input.notes, id],
|
|
)
|
|
.map_err(|e| e.to_string())?;
|
|
if rows == 0 { return Err(format!("API Key {} 不存在", id)); }
|
|
get_api_key(conn, id).ok_or_else(|| "更新后查询失败".into())
|
|
}
|
|
|
|
pub fn delete_api_key_fn(conn: &Connection, id: &str) -> Result<(), String> {
|
|
conn.execute("DELETE FROM api_keys WHERE id=?1", params![id]).map_err(|e| e.to_string())?;
|
|
Ok(())
|
|
}
|
|
|
|
// ── Tauri commands ───────────────────────────────────────────────────────────
|
|
|
|
#[tauri::command]
|
|
pub fn get_api_keys() -> Result<Vec<ApiKey>, String> {
|
|
let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
|
|
Ok(list_api_keys(&conn))
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn add_api_key(input: SaveApiKeyInput) -> Result<ApiKey, String> {
|
|
let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
|
|
create_api_key(&conn, &input)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn edit_api_key(id: String, input: SaveApiKeyInput) -> Result<ApiKey, String> {
|
|
let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
|
|
update_api_key(&conn, &id, &input)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn delete_api_key(id: String) -> Result<(), String> {
|
|
let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
|
|
delete_api_key_fn(&conn, &id)
|
|
}
|