feat: 前端页面优化与入库任务重试/删除
- 概览与检索合并为单一概览页 - 类目/文档管理/入库整合为树形目录知识库页(Library),支持文档搜索 - 入库进度改为右侧 Drawer,支持任务详情、重试、删除 - 后端新增任务重试与删除接口
This commit is contained in:
@@ -80,6 +80,7 @@ class IngestTaskManager:
|
||||
task_id = uuid.uuid4().hex
|
||||
now = _utc_now_iso()
|
||||
filename = self._extract_filename(doc)
|
||||
source = self._extract_source(doc)
|
||||
dedup = get_dedup_strategy(self._redis)
|
||||
|
||||
# 1. 去重命中:直接置 done,复用旧结果,不调 _run
|
||||
@@ -95,6 +96,7 @@ class IngestTaskManager:
|
||||
"result": result_dict,
|
||||
"error": None,
|
||||
"filename": filename,
|
||||
"source": source,
|
||||
}
|
||||
self._schedule_mirror(task_id)
|
||||
logger.info(
|
||||
@@ -113,6 +115,7 @@ class IngestTaskManager:
|
||||
"result": None,
|
||||
"error": None,
|
||||
"filename": filename,
|
||||
"source": source,
|
||||
}
|
||||
self._schedule_mirror(task_id)
|
||||
background = asyncio.create_task(self._run(task_id, doc, dedup))
|
||||
@@ -190,15 +193,62 @@ class IngestTaskManager:
|
||||
"""从文档输入提取展示用文件名:优先 metadata.original_filename,其次 title"""
|
||||
return doc.metadata.get("original_filename") or doc.title or None
|
||||
|
||||
@staticmethod
|
||||
def _extract_source(doc: DocumentInput) -> dict[str, Any]:
|
||||
"""从文档输入提取重试所需的源信息(供 retry 复用,含文件路径/大小)"""
|
||||
return {
|
||||
"text": doc.text,
|
||||
"title": doc.title,
|
||||
"source": doc.source,
|
||||
"metadata": dict(doc.metadata),
|
||||
}
|
||||
|
||||
async def retry(self, task_id: str) -> str | None:
|
||||
"""重试失败/已完成的入库任务:用原 source 重新提交一个新任务
|
||||
|
||||
返回新 task_id;任务不存在或缺少 source 时返回 None。
|
||||
"""
|
||||
record = await self.get(task_id)
|
||||
if record is None:
|
||||
return None
|
||||
source = record.get("source")
|
||||
if not isinstance(source, dict) or not source.get("text"):
|
||||
return None
|
||||
doc = DocumentInput(
|
||||
text=source["text"],
|
||||
title=source.get("title") or "",
|
||||
source=source.get("source") or "",
|
||||
metadata=source.get("metadata") or {},
|
||||
)
|
||||
return await self.submit(doc)
|
||||
|
||||
async def delete(self, task_id: str) -> bool:
|
||||
"""删除入库任务(内存注册表 + Redis 镜像),不存在返回 False"""
|
||||
existed = self._tasks.pop(task_id, None) is not None
|
||||
if self._redis is not None:
|
||||
try:
|
||||
get_client = getattr(self._redis, "_get_client", None)
|
||||
if callable(get_client):
|
||||
await get_client().delete(f"{REDIS_KEY_PREFIX}{task_id}")
|
||||
existed = True
|
||||
except Exception:
|
||||
logger.warning("删除 Redis 任务镜像失败", task_id=task_id, exc_info=True)
|
||||
return existed
|
||||
|
||||
@staticmethod
|
||||
def _to_list_item(record: dict[str, Any]) -> dict[str, Any]:
|
||||
"""从完整任务记录提取列表展示字段"""
|
||||
result = record.get("result")
|
||||
doc_id = result.get("document_id") if isinstance(result, dict) else None
|
||||
source = record.get("source") or {}
|
||||
metadata = source.get("metadata") or {}
|
||||
return {
|
||||
"task_id": record.get("task_id"),
|
||||
"status": record.get("status"),
|
||||
"filename": record.get("filename"),
|
||||
"title": source.get("title"),
|
||||
"source": source.get("source"),
|
||||
"size_bytes": metadata.get("original_size_bytes"),
|
||||
"created_at": record.get("created_at"),
|
||||
"updated_at": record.get("updated_at"),
|
||||
"doc_id": doc_id,
|
||||
|
||||
Reference in New Issue
Block a user