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",