This commit is contained in:
Your Name
2026-08-14 14:37:30 +08:00
parent 21790e35f4
commit 18c15d1262
117 changed files with 28157 additions and 8080 deletions
@@ -12,20 +12,65 @@ os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
from PySide6.QtGui import QFont, QFontDatabase
from PySide6.QtWidgets import QApplication, QWidget
from doctor_workstation.core.permissions import PermissionSet
from doctor_workstation.ui import apply_theme
from doctor_workstation.ui.dialogs import diagnosis as diagnosis_module
from doctor_workstation.ui.dialogs.prescription import PrescriptionEditorDialog
from doctor_workstation.ui.dialogs.prescription import (
PrescriptionDetailDialog,
PrescriptionEditorDialog,
)
from doctor_workstation.ui.dialogs.prescription_ai import PrescriptionAiReportDialog
class VisualRepository:
def list_medicines(self, **_filters: Any) -> dict[str, Any]:
return {"lists": [], "count": 0}
def list_prescription_template_ai_reports(self, template_id: int) -> dict[str, Any]:
report = {
"summary": "益气健脾为主,兼顾养阴安神,适合脾气不足、气阴两虚方向的复核参考。",
"possible_symptoms": ["乏力气短", "食少便溏", "睡眠不安"],
"main_indications": "气阴两虚、脾气不足所见的倦怠与纳差。",
"efficacy": ["益气健脾", "养阴生津", "宁心安神"],
"suitable_people": ["辨证属气阴两虚者", "需由医师结合四诊确认"],
"compatibility_analysis": "黄芪、党参、白术与茯苓协同补气健脾,麦冬、五味子兼顾养阴敛津,酸枣仁与远志用于宁心安神。",
"cautions": ["仍需核对过敏史与现用药", "症状变化时及时复诊"],
"disclaimer": "仅供专业人员辅助审方,不替代辨证、诊断和处方审核。",
}
return {
"prescription_id": template_id,
"can_refresh": True,
"can_edit": True,
"reports": [
{
"report_id": 21,
"model_key": "qwen",
"model_label": "千问",
"model_name": "qwen3.6-35b",
"generated_at": "2026-08-13 10:32:00",
"report": report,
"is_stale": False,
"is_edited": True,
},
{
"report_id": 22,
"model_key": "openai",
"model_label": "OpenAI",
"model_name": "gpt-5.6-sol",
"generated_at": "2026-08-13 10:32:00",
"report": report,
"is_stale": False,
"is_edited": False,
},
],
}
def _seed() -> dict[str, Any]:
return {
"diagnosis_id": 501,
"id": 2501,
"appointment_id": 2501,
"prescription_no": "RX202608130021",
"patient_name": "林晓岚",
"phone": "13800138000",
"gender": 0,
@@ -57,6 +102,8 @@ def _seed() -> dict[str, Any]:
"prescription_name": "宁心辅方",
},
"doctor_name": "陈医生",
"audit_status": 1,
"create_time": "2026-08-13 10:26:00",
"herbs": [
{"medicine_id": 11, "name": "黄芪", "dosage": 15, "formula_type": "主方"},
{"medicine_id": 12, "name": "党参", "dosage": 12, "formula_type": "主方"},
@@ -78,11 +125,6 @@ def _make_editor(host: QWidget) -> PrescriptionEditorDialog:
current_user=SimpleNamespace(id=1, name="陈医生"),
parent=host,
)
# Diagnosis-detail callers apply their scoped sheet after construction. The
# prescription surface owns its own scoped rules, so this also verifies that
# real entry path rather than a renderer-only appearance.
editor.setObjectName("DiagnosisPrescriptionEditor")
editor.setStyleSheet(diagnosis_module.DIAGNOSIS_QSS)
return editor
@@ -101,43 +143,59 @@ def render() -> list[Path]:
if families:
app.setFont(QFont(families[0], 9))
output = Path(__file__).resolve().parents[1] / "artifacts" / "diagnosis_visual"
output = Path(__file__).resolve().parents[1] / "artifacts" / "subwindow_exact"
output.mkdir(parents=True, exist_ok=True)
rendered: list[Path] = []
for host_width, height in ((1440, 900), (1024, 768), (920, 780)):
host = QWidget()
host.resize(host_width, height)
host.show()
editor = _make_editor(host)
editor.show()
_settle(app)
editor.body_scroll.verticalScrollBar().setValue(0)
_settle(app, 3)
width = min(PrescriptionEditorDialog.DRAWER_WIDTH, host_width)
path = output / f"diagnosis_state_prescription_editor_{width}x{height}.png"
if not editor.grab().save(str(path), "PNG"):
raise RuntimeError(f"failed to save {path}")
rendered.append(path)
editor.close()
host.close()
_settle(app, 2)
host = QWidget()
host.resize(1440, 900)
host.show()
editor = _make_editor(host)
editor.show()
_settle(app)
for index, state in ((1, "herbs"), (2, "usage"), (3, "signature")):
editor.tabs.setCurrentIndex(index)
_settle(app, 4)
path = output / f"diagnosis_state_prescription_editor_{state}_1200x900.png"
if not editor.grab().save(str(path), "PNG"):
raise RuntimeError(f"failed to save {path}")
rendered.append(path)
editor.body_scroll.verticalScrollBar().setValue(0)
_settle(app, 4)
path = output / "prescription_editor_860x900.png"
if not editor.grab().save(str(path), "PNG"):
raise RuntimeError(f"failed to save {path}")
rendered.append(path)
editor.close()
host.close()
detail = PrescriptionDetailDialog(
_seed(),
can_open_diagnosis=True,
can_open_orders=True,
)
detail.show()
_settle(app, 10)
path = output / "prescription_detail_920x780.png"
if not detail.grab().save(str(path), "PNG"):
raise RuntimeError(f"failed to save {path}")
rendered.append(path)
detail.close()
_settle(app, 2)
ai_dialog = PrescriptionAiReportDialog(
VisualRepository(),
PermissionSet(["*", "tcm.prescriptionLibrary/editAiReport"]),
)
ai_dialog.open_for(
{
"id": 2501,
"prescription_name": "益气养阴安神方",
"formula_type": "主方",
"herbs": _seed()["herbs"],
}
)
ai_dialog.show()
_settle(app, 16)
path = output / "prescription_ai_report_920x760.png"
if not ai_dialog.grab().save(str(path), "PNG"):
raise RuntimeError(f"failed to save {path}")
rendered.append(path)
ai_dialog.close()
_settle(app, 2)
return rendered