更新
This commit is contained in:
@@ -52,6 +52,7 @@ from PySide6.QtWidgets import (
|
||||
from .. import icons, motion
|
||||
from ..dialogs.issued_prescription_ai import (
|
||||
PrescriptionAiStatisticsDialog,
|
||||
agreement_safe_batch,
|
||||
agreement_text,
|
||||
batch_running,
|
||||
can_open_issued_ai,
|
||||
@@ -1007,6 +1008,10 @@ class PrescriptionsPage(QWidget):
|
||||
self._mutation_pending = False
|
||||
self._ai_statuses: dict[int, dict[str, Any]] = {}
|
||||
self._ai_enabled = False
|
||||
self._agreement_visible = False
|
||||
self._capability_agreement_visible = False
|
||||
self._ai_capability_token = 0
|
||||
self._ai_capability_pending = False
|
||||
self._ai_request_token = 0
|
||||
self._ai_pending = False
|
||||
self._ai_timer = QTimer(self)
|
||||
@@ -1048,7 +1053,7 @@ class PrescriptionsPage(QWidget):
|
||||
self.orders_button.clicked.connect(lambda: self._open_orders())
|
||||
header.add_action(self.orders_button)
|
||||
self.ai_statistics_button = QPushButton("AI 一致度统计", header)
|
||||
self.ai_statistics_button.setVisible(has_permission(permissions, "tcm.prescriptionAi/statistics", default=False) and callable(getattr(repository, "prescription_ai_statistics", None)))
|
||||
self.ai_statistics_button.hide()
|
||||
self.ai_statistics_button.clicked.connect(self._open_ai_statistics)
|
||||
header.add_action(self.ai_statistics_button)
|
||||
self.add_button = QPushButton("新增处方", header)
|
||||
@@ -1437,6 +1442,7 @@ class PrescriptionsPage(QWidget):
|
||||
self._refresh_pending = False
|
||||
self._generation += 1
|
||||
generation = self._generation
|
||||
self._load_ai_capabilities()
|
||||
page_size = self._page_size
|
||||
start_time, end_time = self._date_filters()
|
||||
filters: dict[str, Any] = {
|
||||
@@ -1656,6 +1662,7 @@ class PrescriptionsPage(QWidget):
|
||||
return
|
||||
method = getattr(self.repository, "list_prescription_ai_statuses", None)
|
||||
if not has_permission(self.permissions, "tcm.prescriptionAi/statuses", default=False):
|
||||
self._set_ai_columns(False)
|
||||
self.ai_status_notice.setText("AI 分析:当前账号没有查看分析状态的权限,请联系管理员授权。")
|
||||
return
|
||||
if not callable(method):
|
||||
@@ -1687,8 +1694,8 @@ class PrescriptionsPage(QWidget):
|
||||
def _set_ai_columns(self, enabled: bool) -> None:
|
||||
changed = enabled != self._ai_enabled
|
||||
self._ai_enabled = enabled
|
||||
for column in (11, 12):
|
||||
self.table.setColumnHidden(column, not enabled)
|
||||
self.table.setColumnHidden(11, not enabled)
|
||||
self.table.setColumnHidden(12, not (enabled and self._agreement_visible))
|
||||
if enabled:
|
||||
header = self.table.horizontalHeader()
|
||||
header.moveSection(header.visualIndex(11), header.visualIndex(4) + 1)
|
||||
@@ -1699,10 +1706,54 @@ class PrescriptionsPage(QWidget):
|
||||
if changed:
|
||||
self._decorate_rows()
|
||||
|
||||
def _set_agreement_visible(self, visible: bool) -> None:
|
||||
self._agreement_visible = visible
|
||||
self.table.setColumnHidden(12, not (self._ai_enabled and visible))
|
||||
self.ai_statistics_button.setVisible(
|
||||
visible and has_permission(self.permissions, "tcm.prescriptionAi/statistics", default=False)
|
||||
and callable(getattr(self.repository, "prescription_ai_statistics", None)))
|
||||
if not visible:
|
||||
self._ai_statuses = {key: agreement_safe_batch(row, False) for key, row in self._ai_statuses.items()}
|
||||
for index in range(self.table.rowCount()):
|
||||
item = self.table.item(index, 12)
|
||||
if item is not None:
|
||||
item.setText("")
|
||||
item.setToolTip("")
|
||||
item.setData(Qt.ItemDataRole.AccessibleTextRole, "")
|
||||
|
||||
def _load_ai_capabilities(self) -> None:
|
||||
self._ai_capability_token += 1
|
||||
token, generation = self._ai_capability_token, self._generation
|
||||
self._ai_request_token += 1
|
||||
self._ai_pending = False
|
||||
self._capability_agreement_visible = False
|
||||
self._set_agreement_visible(False)
|
||||
method = getattr(self.repository, "get_prescription_ai_capabilities", None)
|
||||
self._ai_capability_pending = callable(method)
|
||||
if not callable(method):
|
||||
return
|
||||
run_async(method,
|
||||
on_success=lambda result: self._ai_capabilities_ready(result, token, generation),
|
||||
on_error=lambda _error: self._ai_capabilities_ready({}, token, generation))
|
||||
|
||||
def _ai_capabilities_ready(self, result: Any, token: int, generation: int) -> None:
|
||||
if token != self._ai_capability_token or generation != self._generation:
|
||||
return
|
||||
self._ai_capability_pending = False
|
||||
self._capability_agreement_visible = _row_mapping(result).get("agreement_visible") is True
|
||||
self._set_agreement_visible(self._capability_agreement_visible)
|
||||
if self._capability_agreement_visible:
|
||||
# A previous deny discarded scores, including completed cached batches.
|
||||
# Fetch them again after a fresh grant rather than displaying that cache.
|
||||
self._ai_statuses.clear()
|
||||
if self.isVisible() and not self._loading:
|
||||
self._load_ai_statuses()
|
||||
|
||||
def _ai_statuses_ready(self, result: Any, ids: list[int], token: int, generation: int) -> None:
|
||||
if token != self._ai_request_token or generation != self._generation or not self.isVisible():
|
||||
return
|
||||
data = _row_mapping(result)
|
||||
self._set_agreement_visible(self._capability_agreement_visible and data.get("agreement_visible") is True)
|
||||
self._set_ai_columns(data.get("enabled") is True)
|
||||
if not self._ai_enabled:
|
||||
self._ai_timer.stop()
|
||||
@@ -1713,15 +1764,17 @@ class PrescriptionsPage(QWidget):
|
||||
self.ai_status_notice.setToolTip("")
|
||||
self.ai_report_button.setToolTip("自动分析未启用;仍可查看已保存的历史报告。")
|
||||
return
|
||||
self.ai_status_notice.setText("AI 分析已启用:保存手工处方后自动生成两份报告,并显示药味与剂量一致度。")
|
||||
self.ai_status_notice.setText("AI 分析已启用:保存手工处方后自动生成两份报告。"
|
||||
+ ("可查看药味与剂量一致度。" if self._agreement_visible else ""))
|
||||
self.ai_status_notice.setToolTip("")
|
||||
self.ai_report_button.setToolTip("查看两份 AI 报告、候选处方和逐味对照。")
|
||||
self.ai_report_button.setToolTip("查看两份 AI 报告和候选处方。"
|
||||
+ ("可查看逐味对照。" if self._agreement_visible else ""))
|
||||
for value in ids:
|
||||
self._ai_statuses[value] = {}
|
||||
for batch in data.get("items") or []:
|
||||
value = _int(get_value(batch, "prescription_id"), 0)
|
||||
if value in ids:
|
||||
self._ai_statuses[value] = _row_mapping(batch)
|
||||
self._ai_statuses[value] = agreement_safe_batch(batch, self._agreement_visible and _row_mapping(batch).get("agreement_visible") is True)
|
||||
self._render_ai_statuses()
|
||||
if any(batch_running(self._ai_statuses.get(value)) for value in self._visible_ai_ids()):
|
||||
self._ai_timer.start()
|
||||
@@ -1741,13 +1794,13 @@ class PrescriptionsPage(QWidget):
|
||||
if batch is None and not blank:
|
||||
continue
|
||||
state = "" if blank else (state_text(batch) if batch else "尚无分析记录")
|
||||
agreement = "" if blank else agreement_text(batch)
|
||||
agreement = "" if blank or not self._agreement_visible else agreement_text(batch)
|
||||
for column, text in ((11, state), (12, agreement)):
|
||||
item = self.table.item(index, column)
|
||||
if item.text() != text:
|
||||
item.setText(text)
|
||||
changed = True
|
||||
item.setToolTip("" if blank else status_tooltip(batch))
|
||||
item.setToolTip("" if blank or column == 12 and not self._agreement_visible else status_tooltip(batch))
|
||||
item.setData(Qt.ItemDataRole.AccessibleTextRole, text)
|
||||
if changed:
|
||||
self.table.resizeRowsToContents()
|
||||
@@ -1757,6 +1810,7 @@ class PrescriptionsPage(QWidget):
|
||||
def _ai_statuses_error(self, error: Exception, token: int, generation: int) -> None:
|
||||
if token == self._ai_request_token and generation == self._generation:
|
||||
self._ai_timer.stop()
|
||||
self._set_agreement_visible(False)
|
||||
self._set_ai_columns(False)
|
||||
self.ai_status_notice.setText("AI 分析暂不可用:请稍后刷新;持续无法使用时,请联系管理员检查服务。")
|
||||
self.ai_status_notice.setToolTip(friendly_error(error))
|
||||
@@ -1781,13 +1835,13 @@ class PrescriptionsPage(QWidget):
|
||||
if _is_blank_prescription(row):
|
||||
return
|
||||
menu = QMenu(self.table)
|
||||
action = menu.addAction("AI 报告 / 逐味对照")
|
||||
action = menu.addAction("AI 报告 / 逐味对照" if self._agreement_visible else "AI 报告")
|
||||
action.triggered.connect(lambda: self._run_row_action(row, self._open_ai_report))
|
||||
self._ai_context_menu = menu
|
||||
menu.popup(self.table.viewport().mapToGlobal(position))
|
||||
|
||||
def _open_ai_statistics(self) -> None:
|
||||
if not has_permission(self.permissions, "tcm.prescriptionAi/statistics", default=False):
|
||||
if not self._agreement_visible or not has_permission(self.permissions, "tcm.prescriptionAi/statistics", default=False):
|
||||
return
|
||||
dialog = PrescriptionAiStatisticsDialog(self.repository, self.permissions, self)
|
||||
dialog.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, True)
|
||||
@@ -2207,12 +2261,14 @@ class PrescriptionsPage(QWidget):
|
||||
if self.table.rowCount() == 0 and not self._loading:
|
||||
self.refresh()
|
||||
elif not self._loading:
|
||||
self._load_ai_statuses()
|
||||
self._load_ai_capabilities()
|
||||
|
||||
def hideEvent(self, event: Any) -> None:
|
||||
self._ai_timer.stop()
|
||||
self._ai_scroll_timer.stop()
|
||||
self._ai_request_token += 1
|
||||
self._ai_capability_token += 1
|
||||
self._ai_capability_pending = False
|
||||
self._ai_pending = False
|
||||
super().hideEvent(event)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user