88 lines
3.6 KiB
Python
88 lines
3.6 KiB
Python
|
|
from fastapi import APIRouter, Depends, File, Form, UploadFile
|
||
|
|
from sqlalchemy.orm import Session
|
||
|
|
|
||
|
|
from app.core.response import ApiResponse, ok
|
||
|
|
from app.core.user_context import UserContext, get_user_context
|
||
|
|
from app.db.session import get_db
|
||
|
|
from app.repositories.knowledge_base_repository import KnowledgeBaseRepository
|
||
|
|
from app.schemas.knowledge_admin import (
|
||
|
|
KnowledgeDocumentDetailResponse,
|
||
|
|
KnowledgeDocumentListResponse,
|
||
|
|
KnowledgeDocumentUploadResponse,
|
||
|
|
)
|
||
|
|
from app.services.document_ingestion_service import DocumentIngestionService
|
||
|
|
from app.services.knowledge_space_service import KnowledgeSpaceService
|
||
|
|
|
||
|
|
router = APIRouter()
|
||
|
|
|
||
|
|
|
||
|
|
@router.post("/documents/upload", response_model=ApiResponse[KnowledgeDocumentUploadResponse])
|
||
|
|
async def upload_knowledge_document(
|
||
|
|
file: UploadFile = File(..., description="PDF 文件"),
|
||
|
|
document_title: str | None = Form(default=None, description="文档标题"),
|
||
|
|
document_category: str = Form(default="textbook", description="文档分类:textbook/guideline/manual/other"),
|
||
|
|
version: str = Form(default="v1", description="文档版本"),
|
||
|
|
ctx: UserContext = Depends(get_user_context),
|
||
|
|
db: Session = Depends(get_db),
|
||
|
|
):
|
||
|
|
"""知识库上传:内容管理员上传 PDF,并触发机构知识库构建。"""
|
||
|
|
result = await DocumentIngestionService(db).upload_pdf(
|
||
|
|
ctx,
|
||
|
|
file,
|
||
|
|
document_title=document_title,
|
||
|
|
document_category=document_category,
|
||
|
|
version=version,
|
||
|
|
)
|
||
|
|
db.commit()
|
||
|
|
return ok(result)
|
||
|
|
|
||
|
|
|
||
|
|
@router.get("/documents", response_model=ApiResponse[KnowledgeDocumentListResponse])
|
||
|
|
def list_knowledge_documents(
|
||
|
|
ctx: UserContext = Depends(get_user_context),
|
||
|
|
db: Session = Depends(get_db),
|
||
|
|
):
|
||
|
|
"""知识库文档列表:内容管理员查看本机构已上传文档。"""
|
||
|
|
repo = KnowledgeBaseRepository(db)
|
||
|
|
KnowledgeSpaceService(repo).ensure_content_admin(ctx)
|
||
|
|
institution_id = KnowledgeSpaceService(repo).require_institution_id(ctx)
|
||
|
|
items = [_to_detail(item) for item in repo.list_documents(institution_id)]
|
||
|
|
return ok(KnowledgeDocumentListResponse(items=items))
|
||
|
|
|
||
|
|
|
||
|
|
@router.get("/documents/{document_id}", response_model=ApiResponse[KnowledgeDocumentDetailResponse])
|
||
|
|
def get_knowledge_document(
|
||
|
|
document_id: int,
|
||
|
|
ctx: UserContext = Depends(get_user_context),
|
||
|
|
db: Session = Depends(get_db),
|
||
|
|
):
|
||
|
|
"""知识库文档详情:按机构隔离返回 PDF 构建状态。"""
|
||
|
|
repo = KnowledgeBaseRepository(db)
|
||
|
|
KnowledgeSpaceService(repo).ensure_content_admin(ctx)
|
||
|
|
institution_id = KnowledgeSpaceService(repo).require_institution_id(ctx)
|
||
|
|
document = repo.get_document(document_id, institution_id)
|
||
|
|
if not document:
|
||
|
|
from app.core.exceptions import AppError
|
||
|
|
|
||
|
|
raise AppError("KNOWLEDGE_DOCUMENT_NOT_FOUND", "knowledge document not found", 404)
|
||
|
|
return ok(_to_detail(document))
|
||
|
|
|
||
|
|
|
||
|
|
def _to_detail(document) -> KnowledgeDocumentDetailResponse:
|
||
|
|
"""响应转换:把 ORM 文档对象转换为 API 文档详情。"""
|
||
|
|
return KnowledgeDocumentDetailResponse(
|
||
|
|
document_id=document.id,
|
||
|
|
institution_id=document.institution_id,
|
||
|
|
file_name=document.file_name,
|
||
|
|
document_title=document.document_title,
|
||
|
|
document_category=document.document_category,
|
||
|
|
version=document.version,
|
||
|
|
status=document.status,
|
||
|
|
parse_status=document.parse_status,
|
||
|
|
embedding_status=document.embedding_status,
|
||
|
|
chunk_count=document.chunk_count,
|
||
|
|
error_message=document.error_message,
|
||
|
|
created_at=getattr(document, "created_at", None),
|
||
|
|
updated_at=getattr(document, "updated_at", None),
|
||
|
|
)
|