diff --git a/apps/audit/services.py b/apps/audit/services.py index be7ee39..1262555 100644 --- a/apps/audit/services.py +++ b/apps/audit/services.py @@ -142,3 +142,25 @@ def build_history_rows(logs) -> list[dict]: } ) return rows + + +def build_detail_summary(log: AgentAuditLog, conversation, notifications) -> dict: + """ + 组装处理历史详情页的导出摘要与通知回执信息。 + + 详情页模板只负责展示,字段拼装与优先级判断统一放在服务层。 + """ + structured_output = log.structured_output or {} + export_node = None + if conversation and conversation.node_results: + export_node = next( + (node for node in conversation.node_results if node.get("label") == "Word 回填导出"), + None, + ) + latest_notification = notifications.first() if hasattr(notifications, "first") else None + return { + "export_status": structured_output.get("export_status") or (export_node or {}).get("status", "-"), + "download_url": structured_output.get("download_url", ""), + "blocked_items": structured_output.get("blocked_items") or [], + "notification_receipt": latest_notification.receipt if latest_notification else {}, + } diff --git a/apps/audit/views.py b/apps/audit/views.py index 1f23da8..9315cfd 100644 --- a/apps/audit/views.py +++ b/apps/audit/views.py @@ -2,7 +2,7 @@ from django.shortcuts import get_object_or_404, render from .models import AgentAuditLog, NotificationRecord from apps.chat.models import Conversation -from .services import build_history_rows +from .services import build_detail_summary, build_history_rows def log_list(request): @@ -57,8 +57,14 @@ def log_detail(request, log_id: int): batch_id=audit_log.batch_id, ) conversation = Conversation.objects.filter(conversation_id=audit_log.conversation_id).first() + detail_summary = build_detail_summary(audit_log, conversation, notifications) return render( request, "audit/log_detail.html", - {"log": audit_log, "notifications": notifications, "conversation": conversation}, + { + "log": audit_log, + "notifications": notifications, + "conversation": conversation, + "detail_summary": detail_summary, + }, ) diff --git a/templates/audit/log_detail.html b/templates/audit/log_detail.html index a55f3f6..7a15396 100644 --- a/templates/audit/log_detail.html +++ b/templates/audit/log_detail.html @@ -52,6 +52,29 @@ +
+
+

导出状态摘要

+ +
+ +
+

通知回执

+
{{ detail_summary.notification_receipt }}
+
+
+

通知留痕

diff --git a/tests/test_audit.py b/tests/test_audit.py index b6341bf..b783dc1 100644 --- a/tests/test_audit.py +++ b/tests/test_audit.py @@ -397,3 +397,57 @@ def test_audit_list_shows_batch_scale_and_conversation_status(client, db): assert "会话状态" in content assert "failed" in content assert "待复核" in content + + +def test_audit_detail_page_shows_export_summary_and_notification_receipt(client, db): + Conversation.objects.create( + conversation_id="conv-002", + title="产品B", + product_name="产品B", + batch_id="SUB-20260604-002", + task_status="success", + node_results=[ + {"label": "Word 回填导出", "status": "待复核"}, + {"label": "飞书通知", "status": "已完成"}, + ], + ) + log = create_audit_log( + "document_review", + "注册审核智能体", + "导出任务", + AgentResult( + answer="已生成导出草稿", + status="success", + structured_output={ + "export_status": "draft_only", + "download_url": "/downloads/registration-report.docx", + "blocked_items": ["风险项未清零"], + }, + ), + batch_id="SUB-20260604-002", + conversation_id="conv-002", + product_name="产品B", + ) + create_notification_record( + batch_id="SUB-20260604-002", + conversation_id="conv-002", + product_name="产品B", + trigger_source="word_export", + notify_reason="task_completed", + owner_role="注册资料负责人", + feishu_user_id="ou_demo_9", + message_status="sent", + web_detail_url="https://example.com/detail/9", + receipt={"message_id": "msg-9", "status": "sent"}, + ) + + response = client.get(reverse("audit:detail", args=[log.id])) + + content = response.content.decode("utf-8") + assert response.status_code == 200 + assert "导出状态摘要" in content + assert "draft_only" in content + assert "/downloads/registration-report.docx" in content + assert "风险项未清零" in content + assert "通知回执" in content + assert "msg-9" in content