refactor: 前端架构重构 - 提取 CSS 和逻辑到独立模块
前端重构: - 删除旧的大体积 Vue 组件(HomeView, FileManage, TextSplit 等) - 删除旧的 composables(useFormatters, useModels, useProjects) - 新增 core/, page-logic/, pages/, shared/ 模块化目录结构 - 提取 CSS 到 styles/pages/ 目录 - 添加全局样式 variables.css 和 common.css 后端 API 更新: - chunks: 语义分割 API 增强 - files: 文件处理 API 更新 - models: 模型管理 API 更新 - questions: 问答管理 API 更新 - database: 数据库连接优化 - semantic_embedding: 语义嵌入服务优化 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@ from uuid import UUID, uuid4
|
||||
from fastapi import APIRouter, Depends, UploadFile, File, Query
|
||||
from fastapi.responses import FileResponse, PlainTextResponse
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select
|
||||
|
||||
from app.api.response import ApiResponse, PaginatedResponse
|
||||
from app.core.config import get_settings
|
||||
@@ -17,6 +18,7 @@ from app.core.exceptions import ValidationException, NotFoundException
|
||||
from app.core.crud import CRUDBase
|
||||
from app.core.logging import log_success, log_failure
|
||||
from app.models.models import File as FileModel
|
||||
from app.models.models import Chunk, Question
|
||||
from app.schemas.file import FileResponse, FileCreateSchema
|
||||
from markitdown import MarkItDown
|
||||
|
||||
@@ -329,11 +331,27 @@ async def delete_file(
|
||||
file_id: UUID,
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
"""Delete file"""
|
||||
"""Delete file and all related data (markdown, chunks, questions)"""
|
||||
file = await file_crud.get(db, file_id)
|
||||
if not file or file.project_id != project_id:
|
||||
raise NotFoundException("File", file_id)
|
||||
|
||||
# Delete related chunks and their questions (explicit deletion for safety)
|
||||
chunks_result = await db.execute(
|
||||
select(Chunk).where(Chunk.file_id == file_id)
|
||||
)
|
||||
chunks = chunks_result.scalars().all()
|
||||
for chunk in chunks:
|
||||
# Delete questions related to this chunk
|
||||
questions_result = await db.execute(
|
||||
select(Question).where(Question.chunk_id == chunk.id)
|
||||
)
|
||||
questions = questions_result.scalars().all()
|
||||
for question in questions:
|
||||
await db.delete(question)
|
||||
# Delete chunk
|
||||
await db.delete(chunk)
|
||||
|
||||
# Delete file from raw directory
|
||||
if file.file_path and os.path.exists(file.file_path):
|
||||
await asyncio.get_event_loop().run_in_executor(
|
||||
@@ -342,16 +360,27 @@ async def delete_file(
|
||||
file.file_path
|
||||
)
|
||||
|
||||
# Delete file from ready directory (processed markdown)
|
||||
ready_path = Path("/data/code/YG-Datasets/data") / str(project_id) / "ready" / f"{file_id}.md"
|
||||
if ready_path.exists():
|
||||
await asyncio.get_event_loop().run_in_executor(
|
||||
None,
|
||||
os.remove,
|
||||
str(ready_path)
|
||||
)
|
||||
# Delete file from ready directory (processed markdown) - try both naming conventions
|
||||
ready_dir = Path("/data/code/YG-Datasets/data") / str(project_id) / "ready"
|
||||
if ready_dir.exists():
|
||||
# Try file_id.md (from upload process)
|
||||
ready_path = ready_dir / f"{file_id}.md"
|
||||
if ready_path.exists():
|
||||
await asyncio.get_event_loop().run_in_executor(
|
||||
None,
|
||||
os.remove,
|
||||
str(ready_path)
|
||||
)
|
||||
# Try file_id_filename.md (from split process)
|
||||
for md_file in ready_dir.glob(f"{file_id}_*.md"):
|
||||
await asyncio.get_event_loop().run_in_executor(
|
||||
None,
|
||||
os.remove,
|
||||
str(md_file)
|
||||
)
|
||||
|
||||
await file_crud.delete(db, file_id)
|
||||
await db.commit()
|
||||
return ApiResponse.ok(message="File deleted successfully")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user