107 lines
3.3 KiB
Python
107 lines
3.3 KiB
Python
"""
|
|
知识库 API — 上传 / 列表 / 删除 / 来源筛选
|
|
"""
|
|
|
|
from typing import Optional
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Query, status
|
|
from sqlmodel import Session
|
|
|
|
from app.core.deps import get_current_user, require_role
|
|
from app.db.session import get_session
|
|
from app.models.user import User, UserRole
|
|
from app.services.knowledge_service import KnowledgeService
|
|
|
|
|
|
router = APIRouter(prefix="/api/knowledge", tags=["知识库"])
|
|
|
|
|
|
@router.post("/upload")
|
|
async def upload_md_files(
|
|
files: list[UploadFile] = File(...),
|
|
session: Session = Depends(get_session),
|
|
current_user: User = Depends(require_role(UserRole.zhipianren, UserRole.zebian)),
|
|
):
|
|
"""
|
|
上传单个或多个 .md 文件,解析 frontmatter,写入知识库(含向量)。
|
|
仅制片人/责编可用。
|
|
"""
|
|
svc = KnowledgeService()
|
|
results = []
|
|
errors = []
|
|
|
|
for f in files:
|
|
if not f.filename.endswith(".md"):
|
|
errors.append({"file": f.filename, "error": "仅支持 .md 文件"})
|
|
continue
|
|
try:
|
|
content = await f.read()
|
|
item = svc.store_md_file(content, f.filename)
|
|
results.append({
|
|
"id": item.id,
|
|
"title": item.title,
|
|
"source_type": item.source_type,
|
|
})
|
|
except Exception as e:
|
|
errors.append({"file": f.filename, "error": str(e)})
|
|
|
|
return {"uploaded": results, "errors": errors}
|
|
|
|
|
|
@router.get("/items")
|
|
def list_knowledge_items(
|
|
source_type: Optional[str] = Query(None),
|
|
session: Session = Depends(get_session),
|
|
current_user: User = Depends(require_role(UserRole.zhipianren, UserRole.zebian, UserRole.biandao)),
|
|
):
|
|
"""
|
|
知识库列表,支持按 source_type 筛选。三角色均可读。
|
|
"""
|
|
svc = KnowledgeService()
|
|
items = svc.list_items(source_type=source_type)
|
|
return items
|
|
|
|
|
|
@router.delete("/items/{item_id}")
|
|
def delete_knowledge_item(
|
|
item_id: int,
|
|
session: Session = Depends(get_session),
|
|
current_user: User = Depends(require_role(UserRole.zhipianren, UserRole.zebian)),
|
|
):
|
|
"""
|
|
删除知识库条目(级联删除向量)。仅制片人/责编可用。
|
|
"""
|
|
svc = KnowledgeService()
|
|
deleted = svc.delete_item(item_id)
|
|
if not deleted:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="条目不存在")
|
|
return {"message": "删除成功"}
|
|
|
|
|
|
@router.get("/sources")
|
|
def list_distinct_sources(
|
|
session: Session = Depends(get_session),
|
|
current_user: User = Depends(require_role(UserRole.zhipianren, UserRole.zebian, UserRole.biandao)),
|
|
):
|
|
"""
|
|
返回库里所有不重复的具体出处(source_detail),供来源筛选下拉动态生成。
|
|
三角色均可读。
|
|
"""
|
|
svc = KnowledgeService()
|
|
sources = svc.get_distinct_sources()
|
|
return [{"source": s} for s in sources]
|
|
|
|
|
|
@router.get("/grouped")
|
|
def get_grouped_knowledge_items(
|
|
session: Session = Depends(get_session),
|
|
current_user: User = Depends(require_role(UserRole.zhipianren, UserRole.zebian, UserRole.biandao)),
|
|
):
|
|
"""
|
|
返回按 source_type → source_detail 两层聚合的树形结构,
|
|
含「全部」根节点,供知识库树形导航使用。
|
|
三角色均可读。
|
|
"""
|
|
svc = KnowledgeService()
|
|
return svc.get_grouped_items()
|