fix(regulatory): 将条件确认移入对话区
This commit is contained in:
@@ -43,6 +43,7 @@ def workspace(request: HttpRequest) -> HttpResponse:
|
|||||||
current = conversations.first()
|
current = conversations.first()
|
||||||
|
|
||||||
workflow_cards = build_workflow_cards(current) if current else []
|
workflow_cards = build_workflow_cards(current) if current else []
|
||||||
|
condition_confirmation = build_condition_confirmation(workflow_cards)
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
@@ -55,6 +56,7 @@ def workspace(request: HttpRequest) -> HttpResponse:
|
|||||||
"messages": current.messages.all() if current else [],
|
"messages": current.messages.all() if current else [],
|
||||||
"attachments": FileAttachment.objects.filter(conversation=current).order_by("original_name", "-version_no") if current else [],
|
"attachments": FileAttachment.objects.filter(conversation=current).order_by("original_name", "-version_no") if current else [],
|
||||||
"workflow_cards": workflow_cards,
|
"workflow_cards": workflow_cards,
|
||||||
|
"condition_confirmation": condition_confirmation,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -154,6 +156,21 @@ def build_workflow_cards(conversation: Conversation) -> list[dict[str, object]]:
|
|||||||
return sorted(cards, key=lambda item: item["created_at"], reverse=True)[:5]
|
return sorted(cards, key=lambda item: item["created_at"], reverse=True)[:5]
|
||||||
|
|
||||||
|
|
||||||
|
def build_condition_confirmation(workflow_cards: list[dict[str, object]]) -> dict[str, object] | None:
|
||||||
|
for card in workflow_cards:
|
||||||
|
if (
|
||||||
|
card.get("workflow_type") == "regulatory_review"
|
||||||
|
and card.get("status") == RegulatoryReviewBatch.Status.WAITING_USER
|
||||||
|
and card.get("condition_candidates")
|
||||||
|
):
|
||||||
|
return {
|
||||||
|
"id": card["id"],
|
||||||
|
"batch_no": card["batch_no"],
|
||||||
|
"candidates": card["condition_candidates"],
|
||||||
|
}
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _format_risk_label(risk_summary: dict) -> str:
|
def _format_risk_label(risk_summary: dict) -> str:
|
||||||
parts = []
|
parts = []
|
||||||
labels = [
|
labels = [
|
||||||
|
|||||||
@@ -124,6 +124,43 @@
|
|||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{% if condition_confirmation %}
|
||||||
|
<article
|
||||||
|
class="message assistant"
|
||||||
|
id="condition-confirmation-{{ condition_confirmation.id }}"
|
||||||
|
data-node-label="AI 适用条件确认"
|
||||||
|
>
|
||||||
|
<div class="message-avatar">AI</div>
|
||||||
|
<div class="message-bubble">
|
||||||
|
<form
|
||||||
|
class="condition-confirm-form"
|
||||||
|
data-condition-confirm-form
|
||||||
|
data-batch-id="{{ condition_confirmation.id }}"
|
||||||
|
data-confirm-url="/api/review-agent/regulatory-review/{{ condition_confirmation.id }}/conditions/"
|
||||||
|
>
|
||||||
|
{% csrf_token %}
|
||||||
|
<strong>适用条件确认</strong>
|
||||||
|
<p>请确认 {{ condition_confirmation.batch_no }} 的产品类别、注册类型和临床评价路径,确认后我会继续法规核查。</p>
|
||||||
|
{% for field, config in condition_confirmation.candidates.items %}
|
||||||
|
<label>
|
||||||
|
<span>{{ config.label }}</span>
|
||||||
|
{% if config.input_type == "select" %}
|
||||||
|
<select name="{{ field }}">
|
||||||
|
{% for option in config.options %}
|
||||||
|
<option value="{{ option }}"{% if option == config.suggested %} selected{% endif %}>{{ option }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
{% else %}
|
||||||
|
<input type="text" name="{{ field }}" value="{{ config.suggested|default:'' }}">
|
||||||
|
{% endif %}
|
||||||
|
</label>
|
||||||
|
{% endfor %}
|
||||||
|
<button type="submit">确认并继续</button>
|
||||||
|
<p class="condition-confirm-status" data-condition-confirm-status></p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="empty-state">
|
<div class="empty-state">
|
||||||
<p class="eyebrow">审核智能体</p>
|
<p class="eyebrow">审核智能体</p>
|
||||||
@@ -257,33 +294,6 @@
|
|||||||
{% if batch.error_message %}
|
{% if batch.error_message %}
|
||||||
<p class="workflow-error">{{ batch.error_message }}</p>
|
<p class="workflow-error">{{ batch.error_message }}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if batch.workflow_type == "regulatory_review" and batch.status == "waiting_user" and batch.condition_candidates %}
|
|
||||||
<form
|
|
||||||
class="condition-confirm-form"
|
|
||||||
data-condition-confirm-form
|
|
||||||
data-batch-id="{{ batch.id }}"
|
|
||||||
data-confirm-url="/api/review-agent/regulatory-review/{{ batch.id }}/conditions/"
|
|
||||||
>
|
|
||||||
{% csrf_token %}
|
|
||||||
<strong>适用条件确认</strong>
|
|
||||||
{% for field, config in batch.condition_candidates.items %}
|
|
||||||
<label>
|
|
||||||
<span>{{ config.label }}</span>
|
|
||||||
{% if config.input_type == "select" %}
|
|
||||||
<select name="{{ field }}">
|
|
||||||
{% for option in config.options %}
|
|
||||||
<option value="{{ option }}"{% if option == config.suggested %} selected{% endif %}>{{ option }}</option>
|
|
||||||
{% endfor %}
|
|
||||||
</select>
|
|
||||||
{% else %}
|
|
||||||
<input type="text" name="{{ field }}" value="{{ config.suggested|default:'' }}">
|
|
||||||
{% endif %}
|
|
||||||
</label>
|
|
||||||
{% endfor %}
|
|
||||||
<button type="submit">确认并继续</button>
|
|
||||||
<p class="condition-confirm-status" data-condition-confirm-status></p>
|
|
||||||
</form>
|
|
||||||
{% endif %}
|
|
||||||
<ol>
|
<ol>
|
||||||
{% for node in batch.nodes %}
|
{% for node in batch.nodes %}
|
||||||
<li class="node-status status-{{ node.status }}" data-node-code="{{ node.node_code }}">
|
<li class="node-status status-{{ node.status }}" data-node-code="{{ node.node_code }}">
|
||||||
|
|||||||
@@ -102,6 +102,10 @@ def test_workspace_renders_condition_confirmation_form(client, django_user_model
|
|||||||
assert "data-condition-confirm-form" in content
|
assert "data-condition-confirm-form" in content
|
||||||
assert "体外诊断试剂" in content
|
assert "体外诊断试剂" in content
|
||||||
assert "甲胎蛋白检测试剂盒" in content
|
assert "甲胎蛋白检测试剂盒" in content
|
||||||
|
form_index = content.index("data-condition-confirm-form")
|
||||||
|
summary_index = content.index('id="summaryPanel"')
|
||||||
|
assert form_index < summary_index
|
||||||
|
assert "data-condition-confirm-form" not in content[summary_index:]
|
||||||
|
|
||||||
|
|
||||||
def test_workspace_renders_rectification_actions_and_summaries(client, tmp_path, django_user_model):
|
def test_workspace_renders_rectification_actions_and_summaries(client, tmp_path, django_user_model):
|
||||||
|
|||||||
Reference in New Issue
Block a user