diff --git a/apps/audit/services.py b/apps/audit/services.py index 7eb9013..1bdb60a 100644 --- a/apps/audit/services.py +++ b/apps/audit/services.py @@ -144,6 +144,28 @@ def build_history_rows(logs) -> list[dict]: return rows +def build_history_metrics(history_rows: list[dict]) -> list[dict]: + """ + 为处理历史页生成顶部指标卡。 + + 口径保持前台可讲解: + - 处理任务数:当前筛选结果中的执行记录数 + - 成功执行:状态为 success 的记录数 + - 通知已发送:通知状态为 sent 的记录数 + - 高风险阻断:风险等级为 high 的记录数 + """ + total_count = len(history_rows) + success_count = sum(1 for row in history_rows if row["log"].status == "success") + notify_sent_count = sum(1 for row in history_rows if row.get("notify_status") == "sent") + blocked_count = sum(1 for row in history_rows if row.get("risk_status") == "high") + return [ + {"label": "处理任务数", "value": total_count, "note": "按当前筛选条件回看执行留痕。"}, + {"label": "成功执行", "value": success_count, "note": "执行完成并写入审计快照。"}, + {"label": "通知已发送", "value": notify_sent_count, "note": "已生成 sent 状态的通知留痕。"}, + {"label": "高风险阻断", "value": blocked_count, "note": "风险等级为 high 的处理记录。"}, + ] + + def build_detail_summary(log: AgentAuditLog, conversation, notifications) -> dict: """ 组装处理历史详情页的导出摘要与通知回执信息。 diff --git a/apps/audit/views.py b/apps/audit/views.py index 9315cfd..7fe2b9e 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_detail_summary, build_history_rows +from .services import build_detail_summary, build_history_metrics, build_history_rows def log_list(request): @@ -35,11 +35,13 @@ def log_list(request): if (log.structured_output or {}).get("highest_risk_level") == risk_status or (log.structured_output or {}).get("risk_level") == risk_status ] + history_rows = build_history_rows(logs) return render( request, "audit/log_list.html", { - "history_rows": build_history_rows(logs), + "history_rows": history_rows, + "history_metrics": build_history_metrics(history_rows), "selected_scenario_id": scenario_id, "keyword": keyword, "notify_status": notify_status, diff --git a/templates/audit/log_list.html b/templates/audit/log_list.html index 9444d6f..51e1a0d 100644 --- a/templates/audit/log_list.html +++ b/templates/audit/log_list.html @@ -9,6 +9,16 @@

按批次、产品和会话回看审核执行、结构化结论与通知留痕。

+
+ {% for item in history_metrics %} +
+
{{ item.label }}
+
{{ item.value }}
+
{{ item.note }}
+
+ {% endfor %} +
+
@@ -79,19 +89,55 @@ {{ row.log.id }} {{ row.log.scenario_name }} - {{ row.log.product_name|default:"-" }} - {{ row.log.batch_id|default:"-" }} - {{ row.log.conversation_id|default:"-" }} + + {% if row.log.product_name %} + {{ row.log.product_name }} + {% else %} + - + {% endif %} + + + {% if row.log.batch_id %} + {{ row.log.batch_id }} + {% else %} + - + {% endif %} + + + {% if row.log.conversation_id %} + 查看会话 {{ row.log.conversation_id }} + {% else %} + - + {% endif %} + {{ row.batch_scale }} - {{ row.batch_status }} - {{ row.conversation_status }} + + + {{ row.batch_status }} + + + + + {{ row.conversation_status }} + + {{ row.log.get_user_input_summary }} {{ row.log.get_status_display_text }} - {{ row.risk_status }} - {{ row.notify_reason }} - {{ row.notify_status }} + + + {{ row.risk_status }} + + + + {{ row.notify_reason }} + + + + {{ row.notify_status }} + + {{ row.log.model_name }} {{ row.log.created_at|date:"Y-m-d H:i" }} 查看详情 diff --git a/tests/test_audit.py b/tests/test_audit.py index 1969f6e..aef83d3 100644 --- a/tests/test_audit.py +++ b/tests/test_audit.py @@ -399,6 +399,66 @@ def test_audit_list_shows_batch_scale_and_conversation_status(client, db): assert "待复核" in content +def test_audit_list_shows_history_metrics_and_context_links(client, db): + SubmissionBatch.objects.create( + batch_id="SUB-20260604-009", + product_name="产品C", + workflow_type="registration", + conversation_id="conv-009", + file_count=5, + page_count=31, + import_status="completed", + ) + Conversation.objects.create( + conversation_id="conv-009", + title="产品C", + product_name="产品C", + batch_id="SUB-20260604-009", + task_status="success", + node_results=[ + {"label": "风险预警", "status": "已完成"}, + {"label": "飞书通知", "status": "已完成"}, + ], + ) + create_audit_log( + "document_review", + "注册审核智能体", + "产品C 审核", + AgentResult( + answer="完成", + status="success", + structured_output={"highest_risk_level": "medium"}, + ), + batch_id="SUB-20260604-009", + conversation_id="conv-009", + product_name="产品C", + ) + create_notification_record( + batch_id="SUB-20260604-009", + conversation_id="conv-009", + product_name="产品C", + trigger_source="risk_report", + 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"}, + ) + + response = client.get(reverse("audit:list")) + + content = response.content.decode("utf-8") + assert response.status_code == 200 + assert "处理任务数" in content + assert "成功执行" in content + assert "通知已发送" in content + assert "高风险阻断" in content + assert reverse("chat:detail", args=["conv-009"]) in content + assert f"{reverse('documents:list')}?keyword=SUB-20260604-009" in content + assert f"{reverse('audit:list')}?keyword=产品C" in content + + def test_audit_detail_page_shows_export_summary_and_notification_receipt(client, db): Conversation.objects.create( conversation_id="conv-002",