feat: expose acceptance Link AI aggregate data

This commit is contained in:
2026-08-20 17:07:55 +08:00
parent fd83c2d1b2
commit 6bc0f16006
3 changed files with 76 additions and 0 deletions

View File

@@ -22,6 +22,7 @@ from crawler_client import (
collect_keyword_sources,
fetch_content_detail,
get_wen_resources,
match_feishu_notes,
query_collection,
schedule_xapi_screenshots,
)
@@ -965,3 +966,61 @@ def list_acceptance_notes(public_id: str) -> dict[str, Any]:
item["parsed_data"] = json.loads(item.pop("raw_json")) if item.get("raw_json") else None
items.append(item)
return {"items": items, "total": len(items)}
def get_acceptance_link_ai_data(public_id: str) -> dict[str, Any]:
"""返回 Link AI 所需的笔记、AI 采集结果和逐关键词比对结果。"""
with connection() as conn:
task = conn.execute(
"SELECT * FROM acceptance_tasks WHERE public_task_id=?", (public_id,),
).fetchone()
if not task:
raise TaskError("ACCEPTANCE_TASK_NOT_FOUND", "验收任务不存在", 404)
task_data = _task_dict(conn, task)
rows = conn.execute(
"""SELECT a.keyword,a.credential_id,a.attempt_number,a.crawler_task_id,
a.result_json,a.completed_at
FROM acceptance_cookie_attempts a
WHERE a.task_id=? AND a.status='completed' AND a.result_json IS NOT NULL
ORDER BY a.keyword,a.id""",
(task["id"],),
).fetchall()
ai_results = []
for row in rows:
try:
result = json.loads(row["result_json"])
except (TypeError, json.JSONDecodeError):
continue
ai_results.append({
"keyword": row["keyword"],
"credential_id": row["credential_id"],
"attempt_number": row["attempt_number"],
"crawler_task_id": row["crawler_task_id"],
"completed_at": row["completed_at"],
"result": result,
})
comparisons = []
for keyword in task_data["keywords"]:
try:
comparisons.append({
"keyword": keyword,
"status": "completed",
"data": match_feishu_notes(keyword),
})
except Exception as exc:
comparisons.append({
"keyword": keyword,
"status": "failed",
"error": str(exc),
"data": None,
})
return {
"task": task_data,
"notes": list_acceptance_notes(public_id),
"ai_results": {"items": ai_results, "total": len(ai_results)},
"note_matches": {"items": comparisons, "total": len(comparisons)},
"data_scope": "仅包含当前已完成并已入库的数据",
}

8
app.py
View File

@@ -18,6 +18,7 @@ from database import init_database
from acceptance_service import (
create_acceptance_task,
get_acceptance_resources,
get_acceptance_link_ai_data,
get_acceptance_task,
list_acceptance_notes,
list_acceptance_tasks,
@@ -286,6 +287,13 @@ def create_app() -> Flask:
def get_project_acceptance_notes(task_id: str):
return jsonify({"data": list_acceptance_notes(task_id), "request_id": g.request_id})
@app.route("/api/v1/acceptance-tasks/<task_id>/link-ai-data", methods=["GET"])
def get_project_acceptance_link_ai_data(task_id: str):
return jsonify({
"data": get_acceptance_link_ai_data(task_id),
"request_id": g.request_id,
})
@app.route("/api/v1/acceptance-tasks/<task_id>/resume", methods=["POST"])
def resume_project_acceptance_task(task_id: str):
return jsonify({"data": resume_acceptance_task(task_id), "request_id": g.request_id})

View File

@@ -338,6 +338,15 @@ def collect_keyword_sources(keyword: str, credential_id: str | None = None) -> d
)
def match_feishu_notes(keyword: str, task_limit: int = 100) -> dict[str, Any]:
"""调用爬虫服务,比对飞书笔记和问一问采集来源。"""
return _post(
"/api/v1/xhs/feishu-notes/matches",
{"keyword": keyword, "task_limit": task_limit},
retry_transient=True,
)
def resume_collection(crawler_task_id: str) -> dict[str, Any]:
"""沿用原爬虫任务 ID,从 framework 保存的检查点继续采集。"""