style: 统一处理历史状态展示口径
This commit is contained in:
@@ -99,3 +99,11 @@ class NotificationRecord(models.Model):
|
|||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return f"{self.notify_reason}:{self.batch_id}"
|
return f"{self.notify_reason}:{self.batch_id}"
|
||||||
|
|
||||||
|
def get_message_status_display_text(self) -> str:
|
||||||
|
"""返回通知状态的中文展示文案。"""
|
||||||
|
return {
|
||||||
|
self.STATUS_PENDING: "处理中",
|
||||||
|
self.STATUS_SENT: "已发送",
|
||||||
|
self.STATUS_FAILED: "失败",
|
||||||
|
}.get(self.message_status, self.message_status)
|
||||||
|
|||||||
@@ -7,6 +7,36 @@ from .models import AgentAuditLog, NotificationRecord
|
|||||||
|
|
||||||
SUPPORTED_NOTIFY_REASONS = {"task_completed", "task_failed"}
|
SUPPORTED_NOTIFY_REASONS = {"task_completed", "task_failed"}
|
||||||
|
|
||||||
|
RISK_STATUS_DISPLAY = {
|
||||||
|
"high": "已阻断",
|
||||||
|
"medium": "待复核",
|
||||||
|
"low": "已完成",
|
||||||
|
"failed": "失败",
|
||||||
|
"processing": "处理中",
|
||||||
|
"pending": "处理中",
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_STATUS_DISPLAY = {
|
||||||
|
"completed": "已完成",
|
||||||
|
"draft_only": "待复核",
|
||||||
|
"review_required": "待复核",
|
||||||
|
"manual_review": "待复核",
|
||||||
|
"blocked": "已阻断",
|
||||||
|
"failed": "失败",
|
||||||
|
"processing": "处理中",
|
||||||
|
"pending": "处理中",
|
||||||
|
}
|
||||||
|
|
||||||
|
CONVERSATION_STATUS_DISPLAY = {
|
||||||
|
"success": "已完成",
|
||||||
|
"completed": "已完成",
|
||||||
|
"review_required": "待复核",
|
||||||
|
"blocked": "已阻断",
|
||||||
|
"failed": "失败",
|
||||||
|
"processing": "处理中",
|
||||||
|
"pending": "处理中",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def create_audit_log(
|
def create_audit_log(
|
||||||
scenario_id: str,
|
scenario_id: str,
|
||||||
@@ -138,11 +168,15 @@ def build_history_rows(logs) -> list[dict]:
|
|||||||
"conversation": conversation,
|
"conversation": conversation,
|
||||||
"batch_scale": f"{batch.file_count} 份 / {batch.page_count} 页" if batch else "-",
|
"batch_scale": f"{batch.file_count} 份 / {batch.page_count} 页" if batch else "-",
|
||||||
"batch_status": batch.get_import_status_display_text() if batch else "-",
|
"batch_status": batch.get_import_status_display_text() if batch else "-",
|
||||||
"conversation_status": conversation.task_status if conversation else "-",
|
"conversation_status": _get_conversation_status_display_text(
|
||||||
"risk_status": structured_output.get("highest_risk_level")
|
conversation.task_status if conversation else "-"
|
||||||
|
),
|
||||||
|
"risk_status": _get_risk_status_display_text(
|
||||||
|
structured_output.get("highest_risk_level")
|
||||||
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.get_message_status_display_text() if notification else "-",
|
||||||
"notify_reason": notification.notify_reason if notification else "-",
|
"notify_reason": notification.notify_reason if notification else "-",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -161,13 +195,13 @@ def build_history_metrics(history_rows: list[dict]) -> list[dict]:
|
|||||||
"""
|
"""
|
||||||
total_count = len(history_rows)
|
total_count = len(history_rows)
|
||||||
success_count = sum(1 for row in history_rows if row["log"].status == "success")
|
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")
|
notify_sent_count = sum(1 for row in history_rows if row.get("notify_status") == "已发送")
|
||||||
blocked_count = sum(1 for row in history_rows if row.get("risk_status") == "high")
|
blocked_count = sum(1 for row in history_rows if row.get("risk_status") == "已阻断")
|
||||||
return [
|
return [
|
||||||
{"label": "处理任务数", "value": total_count, "note": "按当前筛选条件回看执行留痕。"},
|
{"label": "处理任务数", "value": total_count, "note": "按当前筛选条件回看执行留痕。"},
|
||||||
{"label": "成功执行", "value": success_count, "note": "执行完成并写入审计快照。"},
|
{"label": "成功执行", "value": success_count, "note": "执行完成并写入审计快照。"},
|
||||||
{"label": "通知已发送", "value": notify_sent_count, "note": "已生成 sent 状态的通知留痕。"},
|
{"label": "通知已发送", "value": notify_sent_count, "note": "已生成已发送状态的通知留痕。"},
|
||||||
{"label": "高风险阻断", "value": blocked_count, "note": "风险等级为 high 的处理记录。"},
|
{"label": "高风险阻断", "value": blocked_count, "note": "当前风险状态为已阻断的处理记录。"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -187,15 +221,33 @@ def build_detail_summary(log: AgentAuditLog, conversation, notifications) -> dic
|
|||||||
)
|
)
|
||||||
latest_notification = notifications.first() if hasattr(notifications, "first") else None
|
latest_notification = notifications.first() if hasattr(notifications, "first") else None
|
||||||
return {
|
return {
|
||||||
"export_status": structured_output.get("export_status") or (export_node or {}).get("status", "-"),
|
"export_status": _get_export_status_display_text(
|
||||||
|
structured_output.get("export_status") or (export_node or {}).get("status", "-")
|
||||||
|
),
|
||||||
"download_url": structured_output.get("download_url", ""),
|
"download_url": structured_output.get("download_url", ""),
|
||||||
"output_file_name": output_file.get("file_name", ""),
|
"output_file_name": output_file.get("file_name", ""),
|
||||||
"output_file_relative_path": output_file.get("relative_path", ""),
|
"output_file_relative_path": output_file.get("relative_path", ""),
|
||||||
"export_mode": output_file.get("export_mode", ""),
|
"export_mode": output_file.get("export_mode", ""),
|
||||||
"template_name": structured_output.get("template_name", ""),
|
"template_name": structured_output.get("template_name", ""),
|
||||||
"template_version": structured_output.get("template_version", ""),
|
"template_version": structured_output.get("template_version", ""),
|
||||||
"draft_export_status": structured_output.get("draft_export_status", ""),
|
"draft_export_status": _get_export_status_display_text(
|
||||||
"formal_export_status": structured_output.get("formal_export_status", ""),
|
structured_output.get("draft_export_status", "")
|
||||||
|
),
|
||||||
|
"formal_export_status": _get_export_status_display_text(
|
||||||
|
structured_output.get("formal_export_status", "")
|
||||||
|
),
|
||||||
"blocked_items": structured_output.get("blocked_items") or [],
|
"blocked_items": structured_output.get("blocked_items") or [],
|
||||||
"notification_receipt": latest_notification.receipt if latest_notification else {},
|
"notification_receipt": latest_notification.receipt if latest_notification else {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _get_risk_status_display_text(status: str) -> str:
|
||||||
|
return RISK_STATUS_DISPLAY.get(status, status or "-")
|
||||||
|
|
||||||
|
|
||||||
|
def _get_export_status_display_text(status: str) -> str:
|
||||||
|
return EXPORT_STATUS_DISPLAY.get(status, status or "-")
|
||||||
|
|
||||||
|
|
||||||
|
def _get_conversation_status_display_text(status: str) -> str:
|
||||||
|
return CONVERSATION_STATUS_DISPLAY.get(status, status or "-")
|
||||||
|
|||||||
@@ -100,7 +100,7 @@
|
|||||||
<td>{{ item.notify_reason }}</td>
|
<td>{{ item.notify_reason }}</td>
|
||||||
<td>{{ item.owner_role }}</td>
|
<td>{{ item.owner_role }}</td>
|
||||||
<td>{{ item.feishu_user_id }}</td>
|
<td>{{ item.feishu_user_id }}</td>
|
||||||
<td>{{ item.message_status }}</td>
|
<td>{{ item.get_message_status_display_text }}</td>
|
||||||
<td>{{ item.web_detail_url|default:"-" }}</td>
|
<td>{{ item.web_detail_url|default:"-" }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% empty %}
|
{% empty %}
|
||||||
|
|||||||
@@ -35,17 +35,17 @@
|
|||||||
<label for="id_risk_status">风险状态</label>
|
<label for="id_risk_status">风险状态</label>
|
||||||
<select id="id_risk_status" name="risk_status">
|
<select id="id_risk_status" name="risk_status">
|
||||||
<option value="">全部风险</option>
|
<option value="">全部风险</option>
|
||||||
<option value="high"{% if risk_status == "high" %} selected{% endif %}>high</option>
|
<option value="high"{% if risk_status == "high" %} selected{% endif %}>已阻断</option>
|
||||||
<option value="medium"{% if risk_status == "medium" %} selected{% endif %}>medium</option>
|
<option value="medium"{% if risk_status == "medium" %} selected{% endif %}>待复核</option>
|
||||||
<option value="low"{% if risk_status == "low" %} selected{% endif %}>low</option>
|
<option value="low"{% if risk_status == "low" %} selected{% endif %}>已完成</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</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">
|
||||||
<option value="">全部状态</option>
|
<option value="">全部状态</option>
|
||||||
<option value="sent"{% if notify_status == "sent" %} selected{% endif %}>sent</option>
|
<option value="sent"{% if notify_status == "sent" %} selected{% endif %}>已发送</option>
|
||||||
<option value="failed"{% if notify_status == "failed" %} selected{% endif %}>failed</option>
|
<option value="failed"{% if notify_status == "failed" %} selected{% endif %}>失败</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="button-row">
|
<div class="button-row">
|
||||||
@@ -117,7 +117,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="pill {% if row.conversation_status == 'success' %}pill-success{% elif row.conversation_status == 'failed' %}pill-danger{% else %}pill-signal{% endif %}">
|
<span class="pill {% if row.conversation_status == '已完成' %}pill-success{% elif row.conversation_status == '失败' or row.conversation_status == '已阻断' %}pill-danger{% else %}pill-signal{% endif %}">
|
||||||
{{ row.conversation_status }}
|
{{ row.conversation_status }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
@@ -126,7 +126,7 @@
|
|||||||
<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>
|
<td>
|
||||||
<span class="pill {% if row.risk_status == 'high' %}pill-danger{% elif row.risk_status == 'medium' %}pill-signal{% elif row.risk_status == 'low' %}pill-success{% endif %}">
|
<span class="pill {% if row.risk_status == '已阻断' or row.risk_status == '失败' %}pill-danger{% elif row.risk_status == '待复核' or row.risk_status == '处理中' %}pill-signal{% elif row.risk_status == '已完成' %}pill-success{% endif %}">
|
||||||
{{ row.risk_status }}
|
{{ row.risk_status }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
@@ -134,7 +134,7 @@
|
|||||||
<span class="pill pill-accent">{{ row.notify_reason }}</span>
|
<span class="pill pill-accent">{{ row.notify_reason }}</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="pill {% if row.notify_status == 'sent' %}pill-success{% elif row.notify_status == 'failed' %}pill-danger{% else %}pill-signal{% endif %}">
|
<span class="pill {% if row.notify_status == '已发送' %}pill-success{% elif row.notify_status == '失败' %}pill-danger{% else %}pill-signal{% endif %}">
|
||||||
{{ row.notify_status }}
|
{{ row.notify_status }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -249,9 +249,9 @@ def test_audit_list_shows_risk_and_notification_status(client, db):
|
|||||||
content = response.content.decode("utf-8")
|
content = response.content.decode("utf-8")
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert "风险状态" in content
|
assert "风险状态" in content
|
||||||
assert "high" in content
|
assert "已阻断" in content
|
||||||
assert "通知状态" in content
|
assert "通知状态" in content
|
||||||
assert "sent" in content
|
assert "已发送" in content
|
||||||
assert "通知原因" in content
|
assert "通知原因" in content
|
||||||
assert "task_completed" in content
|
assert "task_completed" in content
|
||||||
|
|
||||||
@@ -414,7 +414,7 @@ def test_audit_list_shows_batch_scale_and_conversation_status(client, db):
|
|||||||
assert "资料规模" in content
|
assert "资料规模" in content
|
||||||
assert "4 份 / 26 页" in content
|
assert "4 份 / 26 页" in content
|
||||||
assert "会话状态" in content
|
assert "会话状态" in content
|
||||||
assert "failed" in content
|
assert "失败" in content
|
||||||
assert "待复核" in content
|
assert "待复核" in content
|
||||||
|
|
||||||
|
|
||||||
@@ -476,6 +476,8 @@ def test_audit_list_shows_history_metrics_and_context_links(client, db):
|
|||||||
assert reverse("chat:detail", args=["conv-009"]) 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('documents:list')}?keyword=SUB-20260604-009" in content
|
||||||
assert f"{reverse('audit:list')}?keyword=产品C" in content
|
assert f"{reverse('audit:list')}?keyword=产品C" in content
|
||||||
|
assert "已发送" in content
|
||||||
|
assert "待复核" in content
|
||||||
|
|
||||||
|
|
||||||
def test_audit_detail_page_shows_export_summary_and_notification_receipt(client, db):
|
def test_audit_detail_page_shows_export_summary_and_notification_receipt(client, db):
|
||||||
@@ -525,11 +527,12 @@ def test_audit_detail_page_shows_export_summary_and_notification_receipt(client,
|
|||||||
content = response.content.decode("utf-8")
|
content = response.content.decode("utf-8")
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert "导出状态摘要" in content
|
assert "导出状态摘要" in content
|
||||||
assert "draft_only" in content
|
assert "待复核" in content
|
||||||
assert "/downloads/registration-report.docx" in content
|
assert "/downloads/registration-report.docx" in content
|
||||||
assert "风险项未清零" in content
|
assert "风险项未清零" in content
|
||||||
assert "通知回执" in content
|
assert "通知回执" in content
|
||||||
assert "msg-9" in content
|
assert "msg-9" in content
|
||||||
|
assert "已发送" in content
|
||||||
|
|
||||||
|
|
||||||
def test_audit_detail_page_shows_export_file_name_and_mode(client, db):
|
def test_audit_detail_page_shows_export_file_name_and_mode(client, db):
|
||||||
@@ -578,3 +581,16 @@ def test_audit_detail_page_shows_export_file_name_and_mode(client, db):
|
|||||||
assert "draft" in content
|
assert "draft" in content
|
||||||
assert "模板版本" in content
|
assert "模板版本" in content
|
||||||
assert "V1.0" in content
|
assert "V1.0" in content
|
||||||
|
assert "待复核" in content
|
||||||
|
|
||||||
|
|
||||||
|
def test_audit_list_uses_chinese_filter_labels_for_risk_and_notification_status(client, db):
|
||||||
|
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 ">失败<" in content
|
||||||
|
|||||||
Reference in New Issue
Block a user