fix(regulatory): 轮询时加载条件确认卡
This commit is contained in:
@@ -23,8 +23,7 @@ def batch_status(request, batch_id: int):
|
||||
workflow_type="regulatory_review",
|
||||
workflow_batch_id=batch.pk,
|
||||
).order_by("id")
|
||||
return JsonResponse(
|
||||
{
|
||||
payload = {
|
||||
"batch": {
|
||||
"id": batch.pk,
|
||||
"workflow_type": "regulatory_review",
|
||||
@@ -46,7 +45,14 @@ def batch_status(request, batch_id: int):
|
||||
for node in nodes
|
||||
],
|
||||
}
|
||||
)
|
||||
if batch.status == RegulatoryReviewBatch.Status.WAITING_USER and (batch.condition_json or {}).get("candidates"):
|
||||
payload["condition_confirmation"] = {
|
||||
"batch_id": batch.pk,
|
||||
"batch_no": batch.batch_no,
|
||||
"confirm_url": f"/api/review-agent/regulatory-review/{batch.pk}/conditions/",
|
||||
"candidates": batch.condition_json["candidates"],
|
||||
}
|
||||
return JsonResponse(payload)
|
||||
|
||||
|
||||
@require_http_methods(["POST"])
|
||||
|
||||
@@ -644,6 +644,74 @@
|
||||
selectWorkflowBatchIndex(activeIndex);
|
||||
}
|
||||
|
||||
function ensureConditionConfirmationCard(confirmation) {
|
||||
if (!chatScroll || !confirmation || !confirmation.candidates) {
|
||||
return;
|
||||
}
|
||||
var cardId = "condition-confirmation-" + confirmation.batch_id;
|
||||
if (document.getElementById(cardId)) {
|
||||
return;
|
||||
}
|
||||
var article = document.createElement("article");
|
||||
article.className = "message assistant";
|
||||
article.id = cardId;
|
||||
article.setAttribute("data-node-label", "AI 适用条件确认");
|
||||
|
||||
var avatar = document.createElement("div");
|
||||
avatar.className = "message-avatar";
|
||||
avatar.textContent = "AI";
|
||||
|
||||
var bubble = document.createElement("div");
|
||||
bubble.className = "message-bubble";
|
||||
var form = document.createElement("form");
|
||||
form.className = "condition-confirm-form";
|
||||
form.setAttribute("data-condition-confirm-form", "");
|
||||
form.setAttribute("data-batch-id", confirmation.batch_id);
|
||||
form.setAttribute("data-confirm-url", confirmation.confirm_url);
|
||||
form.innerHTML =
|
||||
'<input type="hidden" name="csrfmiddlewaretoken" value="' +
|
||||
escapeHtml(new FormData(composer).get("csrfmiddlewaretoken") || "") +
|
||||
'">' +
|
||||
"<strong>适用条件确认</strong>" +
|
||||
"<p>请确认 " +
|
||||
escapeHtml(confirmation.batch_no || "") +
|
||||
" 的产品类别、注册类型和临床评价路径,确认后我会继续法规核查。</p>" +
|
||||
renderConditionFields(confirmation.candidates) +
|
||||
'<button type="submit">确认并继续</button>' +
|
||||
'<p class="condition-confirm-status" data-condition-confirm-status></p>';
|
||||
bubble.appendChild(form);
|
||||
article.appendChild(avatar);
|
||||
article.appendChild(bubble);
|
||||
chatScroll.appendChild(article);
|
||||
bindConditionConfirmForms();
|
||||
scrollChatToBottom();
|
||||
}
|
||||
|
||||
function renderConditionFields(candidates) {
|
||||
var html = "";
|
||||
Object.keys(candidates || {}).forEach(function (field) {
|
||||
var config = candidates[field] || {};
|
||||
html += "<label><span>" + escapeHtml(config.label || field) + "</span>";
|
||||
if (config.input_type === "select") {
|
||||
html += '<select name="' + escapeHtml(field) + '">';
|
||||
(config.options || []).forEach(function (option) {
|
||||
var selected = option === config.suggested ? " selected" : "";
|
||||
html += '<option value="' + escapeHtml(option) + '"' + selected + ">" + escapeHtml(option) + "</option>";
|
||||
});
|
||||
html += "</select>";
|
||||
} else {
|
||||
html +=
|
||||
'<input type="text" name="' +
|
||||
escapeHtml(field) +
|
||||
'" value="' +
|
||||
escapeHtml(config.suggested || "") +
|
||||
'">';
|
||||
}
|
||||
html += "</label>";
|
||||
});
|
||||
return html;
|
||||
}
|
||||
|
||||
async function refreshWorkflowCard(batchId, workflow_type) {
|
||||
if (!summaryPanel || !batchId) {
|
||||
return "";
|
||||
@@ -662,6 +730,9 @@
|
||||
return "";
|
||||
}
|
||||
var payload = await response.json();
|
||||
if (payload.condition_confirmation) {
|
||||
ensureConditionConfirmationCard(payload.condition_confirmation);
|
||||
}
|
||||
var card = ensureWorkflowCard({
|
||||
batch_id: payload.batch.id,
|
||||
batch_no: payload.batch.batch_no,
|
||||
|
||||
@@ -159,5 +159,7 @@ def test_frontend_selects_status_url_by_workflow_type():
|
||||
assert "statusUrlForWorkflow" in script
|
||||
assert "bindConditionConfirmForms" in script
|
||||
assert "data-condition-confirm-form" in script
|
||||
assert "ensureConditionConfirmationCard" in script
|
||||
assert "condition_confirmation" in script
|
||||
assert "bindRectificationActionButtons" in script
|
||||
assert "data-rectification-action" in script
|
||||
|
||||
@@ -43,3 +43,40 @@ def test_regulatory_batch_status_requires_owner(client, django_user_model):
|
||||
assert payload["batch"]["workflow_type"] == "regulatory_review"
|
||||
assert payload["batch"]["batch_no"] == "RR-STATUS"
|
||||
assert payload["nodes"][0]["node_code"] == "prepare"
|
||||
|
||||
|
||||
def test_regulatory_batch_status_exposes_condition_confirmation(client, django_user_model):
|
||||
owner = django_user_model.objects.create_user(username="owner", password="pass")
|
||||
conversation = Conversation.objects.create(user=owner, title="会话")
|
||||
summary = FileSummaryBatch.objects.create(
|
||||
conversation=conversation,
|
||||
user=owner,
|
||||
batch_no="FS-OK",
|
||||
status=FileSummaryBatch.Status.SUCCESS,
|
||||
)
|
||||
batch = RegulatoryReviewBatch.objects.create(
|
||||
conversation=conversation,
|
||||
user=owner,
|
||||
source_summary_batch=summary,
|
||||
batch_no="RR-WAIT",
|
||||
status=RegulatoryReviewBatch.Status.WAITING_USER,
|
||||
condition_json={
|
||||
"confirmed": False,
|
||||
"candidates": {
|
||||
"product_category": {
|
||||
"label": "产品类别",
|
||||
"input_type": "select",
|
||||
"options": ["体外诊断试剂", "医疗器械", "其他"],
|
||||
"suggested": "体外诊断试剂",
|
||||
}
|
||||
},
|
||||
},
|
||||
)
|
||||
client.force_login(owner)
|
||||
|
||||
response = client.get(reverse("regulatory_review_batch_status", args=[batch.pk]))
|
||||
|
||||
payload = response.json()
|
||||
assert payload["batch"]["status"] == RegulatoryReviewBatch.Status.WAITING_USER
|
||||
assert payload["condition_confirmation"]["batch_id"] == batch.pk
|
||||
assert payload["condition_confirmation"]["candidates"]["product_category"]["suggested"] == "体外诊断试剂"
|
||||
|
||||
Reference in New Issue
Block a user