diff --git a/apps/audit/views.py b/apps/audit/views.py index bef925b..383720f 100644 --- a/apps/audit/views.py +++ b/apps/audit/views.py @@ -1,6 +1,7 @@ from django.shortcuts import get_object_or_404, render from .models import AgentAuditLog, NotificationRecord +from apps.chat.models import Conversation def log_list(request): @@ -31,8 +32,9 @@ def log_detail(request, log_id: int): conversation_id=audit_log.conversation_id, batch_id=audit_log.batch_id, ) + conversation = Conversation.objects.filter(conversation_id=audit_log.conversation_id).first() return render( request, "audit/log_detail.html", - {"log": audit_log, "notifications": notifications}, + {"log": audit_log, "notifications": notifications, "conversation": conversation}, ) diff --git a/apps/chat/views.py b/apps/chat/views.py index a025919..83a062e 100644 --- a/apps/chat/views.py +++ b/apps/chat/views.py @@ -1,5 +1,6 @@ from django.utils import timezone from django.shortcuts import get_object_or_404, redirect, render +from django.urls import reverse from agent_core.orchestrator import run_agent from agent_core.results import AgentResult @@ -72,7 +73,10 @@ def detail(request, conversation_id: str): product_name=conversation.product_name, ) _apply_agent_result_to_conversation(conversation, result) - _persist_notification_records(result) + _persist_notification_records( + result, + web_detail_url=reverse("audit:detail", args=[audit_log.id]), + ) active_node = "risk" conversation.refresh_from_db() workspace_summary = _build_workspace_summary(conversation, batch) @@ -97,7 +101,7 @@ def detail(request, conversation_id: str): ) -def _persist_notification_records(result: AgentResult) -> None: +def _persist_notification_records(result: AgentResult, *, web_detail_url: str = "") -> None: payload = result.notification_payload or {} owners = payload.get("owners") or [] if not owners: @@ -112,7 +116,7 @@ def _persist_notification_records(result: AgentResult) -> None: owner_role=owner.get("owner_role", ""), feishu_user_id=owner.get("feishu_user_id", ""), message_status="sent" if result.status == "success" else "failed", - web_detail_url="", + web_detail_url=web_detail_url, receipt={"status": result.status}, ) diff --git a/templates/audit/log_detail.html b/templates/audit/log_detail.html index 261269e..a55f3f6 100644 --- a/templates/audit/log_detail.html +++ b/templates/audit/log_detail.html @@ -34,6 +34,24 @@ +
+

会话节点结果

+ +
+

通知留痕

diff --git a/tests/test_audit.py b/tests/test_audit.py index 75fdcdb..36d690b 100644 --- a/tests/test_audit.py +++ b/tests/test_audit.py @@ -3,6 +3,7 @@ from django.urls import reverse from agent_core.results import AgentResult from apps.audit.models import AgentAuditLog, DemoBusinessRecord, NotificationRecord from apps.audit.services import create_audit_log, create_notification_record +from apps.chat.models import Conversation from agent_core.tools.builtin_tools import query_demo_records @@ -194,3 +195,35 @@ def test_audit_list_supports_batch_and_product_filters(client, db): assert response.status_code == 200 assert "产品A" in content assert "产品B" not in content + + +def test_audit_detail_page_shows_conversation_node_results(client, db): + Conversation.objects.create( + conversation_id="conv-001", + title="产品A", + product_name="产品A", + batch_id="SUB-20260604-001", + task_status="failed", + node_results=[ + {"label": "资料包导入", "status": "已完成"}, + {"label": "风险预警", "status": "已阻断"}, + {"label": "飞书通知", "status": "失败"}, + ], + ) + log = create_audit_log( + "document_review", + "注册审核智能体", + "问题一", + AgentResult(answer="回答一", status="failed"), + batch_id="SUB-20260604-001", + conversation_id="conv-001", + product_name="产品A", + ) + + response = client.get(reverse("audit:detail", args=[log.id])) + + content = response.content.decode("utf-8") + assert response.status_code == 200 + assert "会话节点结果" in content + assert "风险预警 / 已阻断" in content + assert "飞书通知 / 失败" in content diff --git a/tests/test_chat.py b/tests/test_chat.py index a8daa12..c53923c 100644 --- a/tests/test_chat.py +++ b/tests/test_chat.py @@ -170,6 +170,7 @@ def test_chat_execution_creates_notification_record_from_agent_result(client, db record = NotificationRecord.objects.get() assert record.notify_reason == "task_completed" assert record.batch_id == batch.batch_id + assert record.web_detail_url.endswith(f"/audit/{AgentAuditLog.objects.get().id}/") def test_chat_execution_creates_failed_notification_record_and_updates_conversation(client, db, monkeypatch): @@ -220,6 +221,7 @@ def test_chat_execution_creates_failed_notification_record_and_updates_conversat conversation.refresh_from_db() assert record.notify_reason == "task_failed" assert record.message_status == "failed" + assert record.web_detail_url.endswith(f"/audit/{AgentAuditLog.objects.get().id}/") assert conversation.task_status == "failed" assert conversation.node_results[-1]["label"] == "飞书通知"