From d7228dd004a5023169f3f081ed03e3cb750cf596 Mon Sep 17 00:00:00 2001 From: cfdaily Date: Fri, 5 Jun 2026 11:59:23 +0800 Subject: [PATCH] auto-sync: 2026-06-05 11:59:23 --- src/api/project_routes.py | 20 +++++++++++++------- src/blackboard/registry.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/api/project_routes.py b/src/api/project_routes.py index a1b80f2..ff9d1f4 100644 --- a/src/api/project_routes.py +++ b/src/api/project_routes.py @@ -5,7 +5,7 @@ from __future__ import annotations from pathlib import Path from typing import Any, Dict, List, Optional -from fastapi import APIRouter, HTTPException +from fastapi import APIRouter, HTTPException, Query from src.blackboard.registry import ProjectRegistry from src.utils import get_data_root @@ -104,16 +104,22 @@ async def archive_project(project_id: str): @router.delete("/{project_id}") -async def delete_project(project_id: str): - """逻辑删除项目(status→deleted)""" +async def delete_project(project_id: str, physical: bool = Query(False)): + """删除项目(默认逻辑删除,physical=true 物理删除)""" reg = _registry() - # 检查项目存在 info = reg.get_project(project_id) if not info: raise HTTPException(404, f"Project not found: {project_id}") - if not reg.delete_project(project_id): - raise HTTPException(500, "Delete failed") - return {"ok": True} + + if physical: + result = reg.physical_delete_project(project_id) + if not result: + raise HTTPException(500, "Physical delete failed") + return {"ok": True, "deleted": result} + else: + if not reg.delete_project(project_id): + raise HTTPException(500, "Delete failed") + return {"ok": True} @router.patch("/{project_id}") diff --git a/src/blackboard/registry.py b/src/blackboard/registry.py index e6f46ea..50e556a 100644 --- a/src/blackboard/registry.py +++ b/src/blackboard/registry.py @@ -177,6 +177,34 @@ class ProjectRegistry: status="deleted", ) + def physical_delete_project(self, project_id: str) -> Optional[Dict[str, Any]]: + """物理删除项目(删目录 + 删 registry 条目)""" + import shutil + + info = self.get_project(project_id) + if not info: + return None + + # 1. 删除项目目录 + project_dir = self.root / project_id + dir_existed = project_dir.exists() + if dir_existed: + shutil.rmtree(project_dir, ignore_errors=True) + + # 2. 从 registry.db 删除条目 + conn = self._connect() + try: + conn.execute("DELETE FROM projects WHERE id=?", (project_id,)) + conn.commit() + finally: + conn.close() + + return { + "project_id": project_id, + "directory": str(project_dir), + "directory_existed": dir_existed, + } + # =================================================================== # 自动发现 # ===================================================================