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:
Developer
2026-03-19 14:23:34 +08:00
parent a280b4f014
commit 6aa271c4f7
75 changed files with 22636 additions and 6519 deletions

View File

@@ -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")