diff --git a/digital-avatar-app/backend/routers/knowledge.py b/digital-avatar-app/backend/routers/knowledge.py index 77b664e..58a9eec 100644 --- a/digital-avatar-app/backend/routers/knowledge.py +++ b/digital-avatar-app/backend/routers/knowledge.py @@ -32,6 +32,14 @@ class EnabledIn(BaseModel): enabled: bool = True +def _doc_payload(doc: KnowledgeDoc) -> dict: + payload = doc.to_dict() + stored_name = os.path.basename(doc.file_url or "") + stored_path = os.path.join(UPLOAD_DIR, doc.avatar_id, stored_name) + payload["filePresent"] = bool(stored_name and os.path.isfile(stored_path)) + return payload + + def _resolve_user(authorization: str | None, db: Session): if not authorization: return None @@ -61,7 +69,7 @@ def list_docs(avatar_id: str, authorization: str = Header(None), db: Session = D .order_by(KnowledgeDoc.created_at.desc()) .all() ) - return ok([d.to_dict() for d in docs]) + return ok([_doc_payload(d) for d in docs]) @router.post("/avatar/{avatar_id}/knowledge/docs") @@ -121,7 +129,7 @@ async def upload_doc(avatar_id: str, file: UploadFile = File(...), authorization db.commit() db.refresh(doc) - return ok(doc.to_dict()) + return ok(_doc_payload(doc)) @router.delete("/avatar/{avatar_id}/knowledge/docs/{doc_id}") diff --git a/digital-avatar-app/backend/tests/test_knowledge_storage.py b/digital-avatar-app/backend/tests/test_knowledge_storage.py new file mode 100644 index 0000000..89c6f3d --- /dev/null +++ b/digital-avatar-app/backend/tests/test_knowledge_storage.py @@ -0,0 +1,23 @@ +from pathlib import Path +from types import SimpleNamespace +from unittest.mock import patch + +from routers.knowledge import _doc_payload + + +def test_doc_payload_reports_whether_the_persisted_file_exists(tmp_path: Path): + avatar_id = "avatar-1" + stored_name = "knowledge.md" + doc = SimpleNamespace( + avatar_id=avatar_id, + file_url=f"/api/files/{avatar_id}/{stored_name}", + to_dict=lambda: {"id": "doc-1", "fileUrl": f"/api/files/{avatar_id}/{stored_name}"}, + ) + stored_dir = tmp_path / avatar_id + stored_dir.mkdir() + stored_file = stored_dir / stored_name + + with patch("routers.knowledge.UPLOAD_DIR", str(tmp_path)): + assert _doc_payload(doc)["filePresent"] is False + stored_file.write_text("knowledge", encoding="utf-8") + assert _doc_payload(doc)["filePresent"] is True diff --git a/digital-avatar-app/src/api/index.ts b/digital-avatar-app/src/api/index.ts index fe43335..929be23 100644 --- a/digital-avatar-app/src/api/index.ts +++ b/digital-avatar-app/src/api/index.ts @@ -202,6 +202,7 @@ export interface KnowledgeDoc { fileSize: number fileUrl: string status: string + filePresent?: boolean vectorized?: boolean embeddingModel?: string chunkCount?: number diff --git a/digital-avatar-app/src/views/KnowledgeManage.vue b/digital-avatar-app/src/views/KnowledgeManage.vue index 574673c..ac7d5ee 100644 --- a/digital-avatar-app/src/views/KnowledgeManage.vue +++ b/digital-avatar-app/src/views/KnowledgeManage.vue @@ -37,10 +37,10 @@
{{ doc.vectorized ? `已切分 ${doc.chunkCount || 0} 段,可用于对话` : '正在解析并建立知识索引' }}
+{{ doc.filePresent === false ? '原文件不可用,请删除后重新上传' : (doc.vectorized ? `已切分 ${doc.chunkCount || 0} 段,可用于对话` : '正在解析并建立知识索引') }}