dev-manager-tauri/src-tauri/src/commands/groups.rs
lanrtop c598c9b05b feat: add BlueprintPromptModal for blueprint management and sync functionality
- Implemented BlueprintPromptModal component to handle blueprint prompt generation and rule synchronization.
- Added BlueprintStatusBadge to display the current status of blueprints in ProjectCard.
- Integrated blueprint status fetching and synchronization in ProjectCard.
- Enhanced SettingsPage with a new section for MCP service configuration and batch sync for blueprint rules.
- Updated commands to include new blueprint-related functionalities and types.
- Changed application name from "Dev Manager" to "炼境" in various components.
2026-04-04 10:47:27 +09:00

140 lines
5.2 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use crate::db::pool;
use crate::mcp_inject;
use crate::models::{ProductGroup, ProjectGroupMap};
use rusqlite::params;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
pub struct GroupInput {
pub id: Option<String>,
pub name: String,
pub description: Option<String>,
pub space_id: Option<String>,
}
#[tauri::command]
pub fn get_groups(space_id: Option<String>) -> Result<Vec<ProductGroup>, String> {
let conn = pool().get().map_err(|e| e.to_string())?;
let result = match &space_id {
Some(sid) => {
let mut stmt = conn.prepare(
"SELECT * FROM product_groups WHERE space_id = ?1 ORDER BY sort_order ASC, id"
).map_err(|e| e.to_string())?;
let x = stmt.query_map(params![sid], ProductGroup::from_row)
.map_err(|e| e.to_string())?
.collect::<Result<Vec<_>, _>>()
.map_err(|e| e.to_string())?; x
}
None => {
let mut stmt = conn.prepare("SELECT * FROM product_groups ORDER BY sort_order ASC, id").map_err(|e| e.to_string())?;
let x = stmt.query_map([], ProductGroup::from_row)
.map_err(|e| e.to_string())?
.collect::<Result<Vec<_>, _>>()
.map_err(|e| e.to_string())?; x
}
};
Ok(result)
}
#[tauri::command]
pub fn create_group(input: GroupInput) -> Result<(), String> {
let conn = pool().get().map_err(|e| e.to_string())?;
let id = input.id.unwrap_or_else(|| uuid::Uuid::new_v4().to_string());
conn.execute(
"INSERT INTO product_groups (id, name, description, space_id) VALUES (?1, ?2, ?3, ?4)",
params![id, input.name, input.description, input.space_id],
)
.map_err(|e| {
if e.to_string().contains("UNIQUE") { "Group id already exists".into() }
else { e.to_string() }
})?;
Ok(())
}
#[tauri::command]
pub fn update_group(id: String, input: GroupInput) -> Result<(), String> {
let conn = pool().get().map_err(|e| e.to_string())?;
conn.execute(
"UPDATE product_groups SET name = COALESCE(?1, name), description = COALESCE(?2, description) WHERE id = ?3",
params![input.name, input.description, id],
)
.map_err(|e| e.to_string())?;
Ok(())
}
#[tauri::command]
pub fn delete_group(id: String) -> Result<(), String> {
let conn = pool().get().map_err(|e| e.to_string())?;
// 先清除所有成员的 MCP 配置DB cascade 删除之前)
let member_ids: Vec<String> = conn
.prepare("SELECT project_id FROM project_group_map WHERE group_id = ?1")
.map_err(|e| e.to_string())?
.query_map(params![id], |row| row.get::<_, String>(0))
.map_err(|e| e.to_string())?
.filter_map(|r| r.ok())
.collect();
for project_id in &member_ids {
if let Err(e) = mcp_inject::remove_project_mcp(project_id, &id) {
eprintln!("[MCP remove] 删除组时清除失败 project={} group={}: {}", project_id, id, e);
}
}
conn.execute("DELETE FROM product_groups WHERE id = ?1", params![id])
.map_err(|e| e.to_string())?;
Ok(())
}
/// 按传入的 id 顺序批量更新 sort_orderindex 即为新顺序)
#[tauri::command]
pub fn reorder_groups(ids: Vec<String>) -> Result<(), String> {
let conn = pool().get().map_err(|e| e.to_string())?;
for (i, id) in ids.iter().enumerate() {
conn.execute(
"UPDATE product_groups SET sort_order = ?1 WHERE id = ?2",
params![i as i32, id],
)
.map_err(|e| e.to_string())?;
}
Ok(())
}
#[tauri::command]
pub fn get_group_maps() -> Result<Vec<ProjectGroupMap>, String> {
let conn = pool().get().map_err(|e| e.to_string())?;
let mut stmt = conn.prepare("SELECT * FROM project_group_map").map_err(|e| e.to_string())?;
let result = stmt.query_map([], ProjectGroupMap::from_row)
.map_err(|e| e.to_string())?
.collect::<Result<Vec<_>, _>>()
.map_err(|e| e.to_string());
result
}
#[tauri::command]
pub fn add_group_member(project_id: String, group_id: String, role: Option<String>) -> Result<(), String> {
let conn = pool().get().map_err(|e| e.to_string())?;
conn.execute(
"INSERT OR REPLACE INTO project_group_map (project_id, group_id, role) VALUES (?1, ?2, ?3)",
params![project_id, group_id, role],
)
.map_err(|e| e.to_string())?;
// DB 写入成功后注入 MCP 配置(非致命,注入失败不影响成员关系)
if let Err(e) = mcp_inject::inject_project_mcp(&project_id, &group_id) {
eprintln!("[MCP inject] 注入失败 project={} group={}: {}", project_id, group_id, e);
}
Ok(())
}
#[tauri::command]
pub fn remove_group_member(project_id: String, group_id: String) -> Result<(), String> {
let conn = pool().get().map_err(|e| e.to_string())?;
// 先清除 MCP 配置(需要在 DB 记录删除前查询项目路径)
if let Err(e) = mcp_inject::remove_project_mcp(&project_id, &group_id) {
eprintln!("[MCP remove] 清除失败 project={} group={}: {}", project_id, group_id, e);
}
conn.execute(
"DELETE FROM project_group_map WHERE project_id = ?1 AND group_id = ?2",
params![project_id, group_id],
)
.map_err(|e| e.to_string())?;
Ok(())
}