feat: 支持处理历史按风险状态筛选

This commit is contained in:
2026-06-04 01:32:35 +08:00
parent 73c6336600
commit e7e3202714
4 changed files with 60 additions and 1 deletions

View File

@@ -117,6 +117,7 @@ def build_history_rows(logs) -> list[dict]:
or structured_output.get("risk_level") or structured_output.get("risk_level")
or "-", or "-",
"notify_status": notification.message_status if notification else "-", "notify_status": notification.message_status if notification else "-",
"notify_reason": notification.notify_reason if notification else "-",
} }
) )
return rows return rows

View File

@@ -10,6 +10,7 @@ def log_list(request):
scenario_id = (request.GET.get("scenario_id") or "").strip() scenario_id = (request.GET.get("scenario_id") or "").strip()
keyword = (request.GET.get("keyword") or "").strip() keyword = (request.GET.get("keyword") or "").strip()
notify_status = (request.GET.get("notify_status") or "").strip() notify_status = (request.GET.get("notify_status") or "").strip()
risk_status = (request.GET.get("risk_status") or "").strip()
logs = AgentAuditLog.objects.all() logs = AgentAuditLog.objects.all()
if scenario_id: if scenario_id:
logs = logs.filter(scenario_id=scenario_id) logs = logs.filter(scenario_id=scenario_id)
@@ -27,6 +28,13 @@ def log_list(request):
for log in logs for log in logs
if (log.batch_id, log.conversation_id) in matched_pairs if (log.batch_id, log.conversation_id) in matched_pairs
] ]
if risk_status:
logs = [
log
for log in logs
if (log.structured_output or {}).get("highest_risk_level") == risk_status
or (log.structured_output or {}).get("risk_level") == risk_status
]
return render( return render(
request, request,
"audit/log_list.html", "audit/log_list.html",
@@ -35,6 +43,7 @@ def log_list(request):
"selected_scenario_id": scenario_id, "selected_scenario_id": scenario_id,
"keyword": keyword, "keyword": keyword,
"notify_status": notify_status, "notify_status": notify_status,
"risk_status": risk_status,
}, },
) )

View File

@@ -21,6 +21,15 @@
<label for="id_keyword">产品名称 / 批次号</label> <label for="id_keyword">产品名称 / 批次号</label>
<input id="id_keyword" type="text" name="keyword" value="{{ keyword }}" placeholder="例如:新型冠状病毒 或 SUB-20260604-001"> <input id="id_keyword" type="text" name="keyword" value="{{ keyword }}" placeholder="例如:新型冠状病毒 或 SUB-20260604-001">
</div> </div>
<div>
<label for="id_risk_status">风险状态</label>
<select id="id_risk_status" name="risk_status">
<option value="">全部风险</option>
<option value="high"{% if risk_status == "high" %} selected{% endif %}>high</option>
<option value="medium"{% if risk_status == "medium" %} selected{% endif %}>medium</option>
<option value="low"{% if risk_status == "low" %} selected{% endif %}>low</option>
</select>
</div>
<div> <div>
<label for="id_notify_status">通知状态</label> <label for="id_notify_status">通知状态</label>
<select id="id_notify_status" name="notify_status"> <select id="id_notify_status" name="notify_status">
@@ -55,6 +64,7 @@
<th>输入摘要</th> <th>输入摘要</th>
<th>状态</th> <th>状态</th>
<th>风险状态</th> <th>风险状态</th>
<th>通知原因</th>
<th>通知状态</th> <th>通知状态</th>
<th>模型</th> <th>模型</th>
<th>时间</th> <th>时间</th>
@@ -74,13 +84,14 @@
<span class="pill {% if row.log.status == 'success' %}pill-success{% else %}pill-danger{% endif %}">{{ row.log.get_status_display_text }}</span> <span class="pill {% if row.log.status == 'success' %}pill-success{% else %}pill-danger{% endif %}">{{ row.log.get_status_display_text }}</span>
</td> </td>
<td>{{ row.risk_status }}</td> <td>{{ row.risk_status }}</td>
<td>{{ row.notify_reason }}</td>
<td>{{ row.notify_status }}</td> <td>{{ row.notify_status }}</td>
<td>{{ row.log.model_name }}</td> <td>{{ row.log.model_name }}</td>
<td>{{ row.log.created_at|date:"Y-m-d H:i" }}</td> <td>{{ row.log.created_at|date:"Y-m-d H:i" }}</td>
<td><a class="button" href="{% url 'audit:detail' row.log.id %}">查看详情</a></td> <td><a class="button" href="{% url 'audit:detail' row.log.id %}">查看详情</a></td>
</tr> </tr>
{% empty %} {% empty %}
<tr><td colspan="12">暂无处理历史,先去执行一次审核任务。</td></tr> <tr><td colspan="13">暂无处理历史,先去执行一次审核任务。</td></tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>

View File

@@ -232,6 +232,8 @@ def test_audit_list_shows_risk_and_notification_status(client, db):
assert "high" in content assert "high" in content
assert "通知状态" in content assert "通知状态" in content
assert "sent" in content assert "sent" in content
assert "通知原因" in content
assert "task_completed" in content
def test_audit_list_can_filter_by_notification_status(client, db): def test_audit_list_can_filter_by_notification_status(client, db):
@@ -286,6 +288,42 @@ def test_audit_list_can_filter_by_notification_status(client, db):
assert "产品A" not in content assert "产品A" not in content
def test_audit_list_can_filter_by_risk_status(client, db):
create_audit_log(
"document_review",
"注册审核智能体",
"问题一",
AgentResult(
answer="回答一",
status="success",
structured_output={"highest_risk_level": "high"},
),
batch_id="SUB-20260604-001",
conversation_id="conv-001",
product_name="产品A",
)
create_audit_log(
"document_review",
"注册审核智能体",
"问题二",
AgentResult(
answer="回答二",
status="success",
structured_output={"highest_risk_level": "low"},
),
batch_id="SUB-20260604-002",
conversation_id="conv-002",
product_name="产品B",
)
response = client.get(reverse("audit:list"), {"risk_status": "high"})
content = response.content.decode("utf-8")
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): def test_audit_detail_page_shows_conversation_node_results(client, db):
Conversation.objects.create( Conversation.objects.create(
conversation_id="conv-001", conversation_id="conv-001",