更新
This commit is contained in:
@@ -64,6 +64,7 @@ DEMO_PERMISSIONS: tuple[str, ...] = (
|
||||
"tcm.diagnosis/editAiReport",
|
||||
"tcm.diagnosis/aiAnalysis",
|
||||
"tcm.diagnosis/aiAssistant",
|
||||
"tcm.diagnosis/aiGeneratePrescription",
|
||||
"tcm.diagnosis/patientAiReports",
|
||||
"tcm.diagnosis/generatePatientAiReport",
|
||||
"tcm.diagnosis/dailyRecord",
|
||||
|
||||
@@ -854,6 +854,11 @@ QUICK_PROMPTS: tuple[tuple[str, str], ...] = (
|
||||
("并发症风险评估", "请评估并发症风险并给出随访要点。"),
|
||||
("生成问诊问题", "请生成接下来应向患者确认的关键问诊问题。"),
|
||||
)
|
||||
AI_PRESCRIPTION_PERMISSION = "tcm.diagnosis/aiGeneratePrescription"
|
||||
PRESCRIPTION_CREATE_PERMISSIONS = (
|
||||
"tcm.diagnosis/chufang",
|
||||
"tcm.diagnosis/kaifang",
|
||||
)
|
||||
TOOL_ITEMS: tuple[tuple[str, str, str], ...] = (
|
||||
("chart", "分析病历", "请根据当前病历给出辨证与病情摘要。"),
|
||||
("trend", "血糖趋势", "请评估该患者的血糖控制情况与趋势。"),
|
||||
@@ -3662,6 +3667,8 @@ class AiConsultDialog(QDialog):
|
||||
hint.setObjectName("AiConsultComposerLabel")
|
||||
chips.addWidget(hint)
|
||||
for label, prompt in QUICK_PROMPTS[:3]:
|
||||
if label == "AI 生成处方" and not self._can_generate_ai_prescription():
|
||||
continue
|
||||
button = QPushButton(label)
|
||||
button.setObjectName("AiConsultChipButton")
|
||||
button.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||
@@ -5464,6 +5471,13 @@ class AiConsultDialog(QDialog):
|
||||
def _submit(self) -> None:
|
||||
self._ask(self.input.text())
|
||||
|
||||
def _can_generate_ai_prescription(self) -> bool:
|
||||
return has_permission(
|
||||
self.permissions, AI_PRESCRIPTION_PERMISSION, default=False
|
||||
) and has_permission(
|
||||
self.permissions, PRESCRIPTION_CREATE_PERMISSIONS, default=False
|
||||
)
|
||||
|
||||
def _handle_local_action(self, text: str) -> bool:
|
||||
if not _is_open_prescription_intent(text):
|
||||
return False
|
||||
@@ -5474,9 +5488,8 @@ class AiConsultDialog(QDialog):
|
||||
text,
|
||||
time_text=datetime.now().strftime("%H:%M"),
|
||||
)
|
||||
can_prescribe = any(
|
||||
has_permission(self.permissions, code, default=False)
|
||||
for code in ("tcm.diagnosis/chufang", "tcm.diagnosis/kaifang")
|
||||
can_prescribe = has_permission(
|
||||
self.permissions, PRESCRIPTION_CREATE_PERMISSIONS, default=False
|
||||
)
|
||||
if not can_prescribe:
|
||||
self._append_bubble(
|
||||
@@ -5485,6 +5498,15 @@ class AiConsultDialog(QDialog):
|
||||
time_text="系统",
|
||||
)
|
||||
return True
|
||||
if not has_permission(
|
||||
self.permissions, AI_PRESCRIPTION_PERMISSION, default=False
|
||||
):
|
||||
self._append_bubble(
|
||||
"ai",
|
||||
"当前账号没有 AI 生成处方权限,无法生成处方草稿。",
|
||||
time_text="系统",
|
||||
)
|
||||
return True
|
||||
if not callable(getattr(self.repository, "create_prescription", None)):
|
||||
self._append_bubble(
|
||||
"ai",
|
||||
|
||||
@@ -197,6 +197,52 @@ def test_prescription_action_without_permission_does_not_call_ai_or_repository(
|
||||
dialog.close()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("grants", "visible"),
|
||||
[
|
||||
(["tcm.diagnosis/aiAssistant"], False),
|
||||
(["tcm.diagnosis/aiAssistant", "tcm.diagnosis/chufang"], False),
|
||||
(["tcm.diagnosis/aiAssistant", "tcm.diagnosis/aiGeneratePrescription"], False),
|
||||
(["tcm.diagnosis/aiAssistant", "tcm.diagnosis/chufang", "tcm.diagnosis/aiGeneratePrescription"], True),
|
||||
],
|
||||
)
|
||||
def test_ai_prescription_quick_prompt_requires_both_permissions(
|
||||
application: QApplication,
|
||||
grants: list[str],
|
||||
visible: bool,
|
||||
) -> None:
|
||||
dialog = AiConsultDialog(DemoDoctorRepository(), PermissionSet(grants))
|
||||
buttons = dialog.findChildren(QPushButton, "AiConsultChipButton")
|
||||
assert ("AI 生成处方" in [button.text() for button in buttons]) is visible
|
||||
dialog.close()
|
||||
|
||||
|
||||
def test_prescription_action_with_write_permission_but_without_ai_grant_is_blocked(
|
||||
application: QApplication,
|
||||
) -> None:
|
||||
class Repository:
|
||||
def create_prescription(self, _payload: Any) -> None:
|
||||
raise AssertionError("must not create without AI prescription permission")
|
||||
|
||||
def generate_ai_prescription(self, _diagnosis_id: int) -> None:
|
||||
raise AssertionError("must not generate without AI prescription permission")
|
||||
|
||||
dialog = AiConsultDialog(
|
||||
Repository(),
|
||||
PermissionSet(["tcm.diagnosis/aiAssistant", "tcm.diagnosis/chufang"]),
|
||||
)
|
||||
dialog.diagnosis_id = 501
|
||||
dialog._ask("开个处方")
|
||||
application.processEvents()
|
||||
bodies = [
|
||||
browser.toPlainText()
|
||||
for browser in dialog.findChildren(QTextBrowser, "AiConsultBubbleText")
|
||||
]
|
||||
assert any("没有 AI 生成处方权限" in body for body in bodies)
|
||||
assert dialog._stream_worker is None
|
||||
dialog.close()
|
||||
|
||||
|
||||
def test_prescription_action_opens_editor_and_forces_current_diagnosis_ownership(
|
||||
application: QApplication,
|
||||
immediate_async: None,
|
||||
@@ -298,7 +344,7 @@ def test_prescription_action_opens_editor_and_forces_current_diagnosis_ownership
|
||||
dialog = AiConsultDialog(
|
||||
Repository(),
|
||||
PermissionSet(
|
||||
["tcm.diagnosis/aiAssistant", "tcm.diagnosis/chufang"]
|
||||
["tcm.diagnosis/aiAssistant", "tcm.diagnosis/chufang", "tcm.diagnosis/aiGeneratePrescription"]
|
||||
),
|
||||
parent=host,
|
||||
)
|
||||
@@ -366,7 +412,7 @@ def test_prescription_action_rejects_mismatched_patient_detail(
|
||||
dialog = AiConsultDialog(
|
||||
Repository(),
|
||||
PermissionSet(
|
||||
["tcm.diagnosis/aiAssistant", "tcm.diagnosis/chufang"]
|
||||
["tcm.diagnosis/aiAssistant", "tcm.diagnosis/chufang", "tcm.diagnosis/aiGeneratePrescription"]
|
||||
),
|
||||
)
|
||||
dialog.diagnosis_id = 501
|
||||
|
||||
Reference in New Issue
Block a user