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
@@ -69,6 +69,7 @@ from ..widgets import (
page_total,
run_async,
)
from .prescription_ai import can_open_diagnosis_ai_report, present_diagnosis_ai_report
_PHONE_PERMISSION = "tcm.diagnosis/phonePlain"
_PATIENT_ORDERS_PERMISSION = "tcm.diagnosis/patientOrders"
@@ -186,38 +187,38 @@ _ORDER_OFFSET_HELP = (
_ORDER_DETAIL_QSS = """
QDialog#DiagnosisOrderDetailOverlay { background: transparent; }
QFrame#DiagnosisOrderDetailScrim { background: rgba(8, 11, 20, 0.78); border: 0; }
QFrame#DiagnosisOrderDetailScrim { background: rgba(30, 64, 175, 0.18); border: 0; }
QFrame#DiagnosisOrderDetailDrawer {
background: #F5F7FB;
background: #F7F9FE;
border: 0;
border-left: 1px solid #D8DEEA;
border-left: 1px solid #DDE7FF;
}
QFrame#DiagnosisOrderDetailHeader {
background: #FFFFFF;
border: 0;
border-bottom: 1px solid #D8DEEA;
border-bottom: 1px solid #DDE7FF;
}
QLabel#DiagnosisOrderDetailTitle { color: #172033; font-size: 19px; font-weight: 650; }
QLabel#DiagnosisOrderDetailMeta { color: #667085; font-size: 12px; }
QLabel#DiagnosisOrderDetailTitle { color: #15224A; font-size: 19px; font-weight: 650; }
QLabel#DiagnosisOrderDetailMeta { color: #7481A3; font-size: 12px; }
QLabel#DiagnosisOrderReadonlyBadge {
color: #667085;
background: #F7F8FC;
border: 1px solid #D8DEEA;
color: #3F4E75;
background: #F7F9FE;
border: 1px solid #E2E7F4;
border-radius: 4px;
padding: 3px 7px;
font-size: 11px;
font-weight: 600;
}
QScrollArea#DiagnosisOrderDetailScroll { border: 0; background: #F5F7FB; }
QScrollArea#DiagnosisOrderDetailScroll > QWidget > QWidget { background: #F5F7FB; }
QScrollArea#DiagnosisOrderDetailScroll { border: 0; background: #F7F9FE; }
QScrollArea#DiagnosisOrderDetailScroll > QWidget > QWidget { background: #F7F9FE; }
QFrame[orderAmountCard="true"] {
background: #FFFFFF;
border: 1px solid #D8DEEA;
border-radius: 7px;
border: 1px solid #DDE7FF;
border-radius: 9px;
}
QLabel[orderAmountTitle="true"] { color: #667085; font-size: 11px; font-weight: 550; }
QLabel[orderAmountTitle="true"] { color: #7481A3; font-size: 11px; font-weight: 550; }
QLabel[orderAmountValue="true"] {
color: #172033;
color: #15224A;
font-size: 18px;
font-weight: 700;
}
@@ -226,34 +227,34 @@ QLabel[orderAmountTone="success"] { color: #16876C; }
QLabel[orderAmountTone="warning"] { color: #9A6813; }
QFrame[orderDetailSection="true"] {
background: #FFFFFF;
border: 1px solid #D8DEEA;
border: 1px solid #E2E7F4;
border-radius: 10px;
}
QLabel[orderSectionTitle="true"] { color: #15224A; font-size: 15px; font-weight: 650; }
QLabel[orderSectionHint="true"] { color: #7481A3; font-size: 11px; }
QFrame[orderField="true"] {
background: #F2F6FE;
border: 1px solid #E2E7F4;
border-radius: 7px;
}
QLabel[orderSectionTitle="true"] { color: #172033; font-size: 15px; font-weight: 650; }
QLabel[orderSectionHint="true"] { color: #667085; font-size: 11px; }
QFrame[orderField="true"] {
background: #F7F8FC;
border: 1px solid #D8DEEA;
border-radius: 5px;
}
QLabel[orderFieldLabel="true"] { color: #667085; font-size: 11px; }
QLabel[orderFieldValue="true"] { color: #172033; font-size: 13px; }
QLabel[orderFieldLabel="true"] { color: #7481A3; font-size: 11px; }
QLabel[orderFieldValue="true"] { color: #15224A; font-size: 13px; }
QLabel[orderEmptyState="true"] {
color: #667085;
background: #F7F8FC;
border: 1px dashed #D8DEEA;
color: #7481A3;
background: #F2F6FE;
border: 1px dashed #C9D8F2;
border-radius: 5px;
padding: 18px 12px;
font-size: 12px;
}
QFrame#DiagnosisOrderTimelineItem { border: 0; border-left: 2px solid #D8DEEA; }
QLabel#DiagnosisOrderTimelineTime { color: #667085; font-size: 11px; }
QLabel#DiagnosisOrderTimelineTitle { color: #172033; font-size: 12px; font-weight: 600; }
QLabel#DiagnosisOrderTimelineBody { color: #667085; font-size: 12px; }
QFrame#DiagnosisOrderTimelineItem { border: 0; border-left: 2px solid #93B4F4; }
QLabel#DiagnosisOrderTimelineTime { color: #7481A3; font-size: 11px; }
QLabel#DiagnosisOrderTimelineTitle { color: #15224A; font-size: 12px; font-weight: 600; }
QLabel#DiagnosisOrderTimelineBody { color: #7481A3; font-size: 12px; }
QFrame#DiagnosisOrderDetailFooter {
background: #FFFFFF;
border: 0;
border-top: 1px solid #D8DEEA;
border-top: 1px solid #DDE7FF;
}
"""
@@ -973,8 +974,8 @@ class DiagnosisDialog(QDialog):
back.setCursor(Qt.CursorShape.PointingHandCursor)
back.setStyleSheet(
"QPushButton{height:32px;padding:0 8px;border:0;background:transparent;"
"color:#78A7FF;font-size:13px;font-weight:500;}"
"QPushButton:hover,QPushButton:focus{background:#1B2440;border-radius:6px;}"
"color:#5265F6;font-size:13px;font-weight:500;}"
"QPushButton:hover,QPushButton:focus{background:#F0F2FF;border-radius:6px;}"
)
back.clicked.connect(self.reject)
left_layout.addWidget(back)
@@ -990,7 +991,7 @@ class DiagnosisDialog(QDialog):
self.readonly_hero_name.setObjectName("DiagnosisReadonlyPatientName")
right_layout.addWidget(self.readonly_hero_name)
self.readonly_hero_meta = QLabel("—")
self.readonly_hero_meta.setStyleSheet("color:#9AA7C0; font-size:13px;")
self.readonly_hero_meta.setObjectName("DiagnosisReadonlyHeroMeta")
right_layout.addWidget(self.readonly_hero_meta)
self.readonly_status = QLabel("从未打卡")
self.readonly_status.setObjectName("DiagnosisReadonlyStatus")
@@ -1008,9 +1009,18 @@ class DiagnosisDialog(QDialog):
layout = QVBoxLayout(card)
layout.setContentsMargins(18, 18, 18, 18)
layout.setSpacing(14)
heading_row = QHBoxLayout()
heading_row.setContentsMargins(0, 0, 0, 0)
heading_row.setSpacing(12)
heading = QLabel("患者信息")
heading.setObjectName("DiagnosisReadonlyCardTitle")
layout.addWidget(heading)
heading_row.addWidget(heading, 1)
self.readonly_ai_button = QPushButton("AI 报告", card)
self.readonly_ai_button.setProperty("variant", "secondary")
self.readonly_ai_button.setCursor(Qt.CursorShape.PointingHandCursor)
self.readonly_ai_button.clicked.connect(self._open_ai_report)
heading_row.addWidget(self.readonly_ai_button, 0)
layout.addLayout(heading_row)
patient_hero = QFrame()
patient_hero.setObjectName("DiagnosisReadonlyPatientHero")
hero_layout = QVBoxLayout(patient_hero)
@@ -1186,7 +1196,7 @@ class DiagnosisDialog(QDialog):
privacy_layout.setContentsMargins(12, 9, 12, 9)
self.privacy_label = QLabel("存在未完成的业务订单,患者基本信息不可修改")
self.privacy_label.setWordWrap(True)
self.privacy_label.setStyleSheet("color:#E4B967; font-size:12px;")
self.privacy_label.setObjectName("DiagnosisPrivacyText")
privacy_layout.addWidget(self.privacy_label)
self.privacy_banner.hide()
layout.addWidget(self.privacy_banner)
@@ -1445,7 +1455,6 @@ class DiagnosisDialog(QDialog):
toolbar_layout.setContentsMargins(14, 10, 14, 10)
label = QLabel("复诊统计起始偏移")
label.setObjectName("DiagnosisOrderOffsetLabel")
label.setStyleSheet("color:#9AA7C0; font-size:12px; font-weight:500;")
label.setToolTip(_ORDER_OFFSET_HELP)
toolbar_layout.addWidget(label)
help_button = QPushButton("?")
@@ -1454,12 +1463,6 @@ class DiagnosisDialog(QDialog):
help_button.setToolTip(_ORDER_OFFSET_HELP)
help_button.setFixedSize(22, 22)
help_button.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
help_button.setStyleSheet(
"QPushButton{color:#9AA7C0;border:1px solid #29334F;border-radius:11px;"
"background:#151D31;padding:0;font-size:12px;font-weight:600;}"
"QPushButton:hover,QPushButton:focus{color:#EEF2FF;border-color:#6675F5;"
"background:#1B2440;}"
)
toolbar_layout.addWidget(help_button)
self.order_offset_help = help_button
self.order_offset = QSpinBox()
@@ -1473,7 +1476,6 @@ class DiagnosisDialog(QDialog):
self.order_offset_preview = QLabel("第 1 笔实单计为一诊")
self.order_offset_preview.setObjectName("DiagnosisOrderOffsetPreview")
self.order_offset_preview.setToolTip(_ORDER_OFFSET_HELP)
self.order_offset_preview.setStyleSheet("color:#9AA7C0; font-size:12px;")
toolbar_layout.addWidget(self.order_offset_preview)
offset_save = QPushButton("保存")
offset_save.setProperty("variant", "primary")
@@ -1486,7 +1488,7 @@ class DiagnosisDialog(QDialog):
layout.addWidget(self.orders_table, 1)
footer = QHBoxLayout()
self.orders_summary = QLabel("共 0 条")
self.orders_summary.setStyleSheet("color:#9AA7C0; font-size:12px;")
self.orders_summary.setObjectName("DiagnosisOrdersSummary")
footer.addWidget(self.orders_summary)
footer.addStretch(1)
self.orders_previous = QPushButton("上一页")
@@ -1655,6 +1657,9 @@ class DiagnosisDialog(QDialog):
self._can_note_delete = has_permission(
self.permissions, _NOTE_DELETE_PERMISSION, default=False
) and callable(getattr(self.repository, "delete_doctor_note_image", None))
if hasattr(self, "readonly_ai_button"):
self.readonly_ai_button.setVisible(can_open_diagnosis_ai_report(self.permissions))
self.readonly_ai_button.setEnabled(self._diagnosis_id > 0)
current_key = self.tabs.tabBar().tabData(self.tabs.currentIndex())
self.tabs.clear()
for key, label, codes in _TAB_DEFINITIONS:
@@ -1862,6 +1867,30 @@ class DiagnosisDialog(QDialog):
self._owner_filter_installed = False
super().done(result)
def _open_ai_report(self) -> None:
if not can_open_diagnosis_ai_report(self.permissions):
return
if self._diagnosis_id <= 0:
return
detail = self._detail if isinstance(self._detail, Mapping) else {}
diagnosis = get_value(detail, "diagnosis", None)
row = dict(diagnosis) if isinstance(diagnosis, Mapping) else dict(detail)
row.update(
{
"id": self._diagnosis_id,
"diagnosis_id": self._diagnosis_id,
"patient_name": first_value(
row,
"patient_name",
"name",
default=self.readonly_patient_title.text()
if hasattr(self, "readonly_patient_title")
else "患者",
),
}
)
present_diagnosis_ai_report(self.repository, self.permissions, self, row)
def open_view_only(self, diagnosis_id: int, *, seed: Any = None) -> None:
self.open_for(diagnosis_id, editable=False, seed=seed, view_only=True)
@@ -2373,7 +2402,9 @@ class DiagnosisDialog(QDialog):
if key == "appetite" and raw in (None, "", [], ()):
raw = first_value(diagnosis, "oral_condition", "mouth_condition", default="")
if key == "diagnosis_type":
raw = _diagnosis_type_value(raw)
raw = _diagnosis_type_value(raw) or _diagnosis_type_value(
first_value(diagnosis, "consultation_type", default="")
)
if key == "gender":
gender_token = str(raw).strip().lower() if raw not in (None, "") else ""
if gender_token in {"2", "f", "female", "女"}: