更新bug
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import sqlite3
|
||||
from collections.abc import Mapping, Sequence
|
||||
from contextlib import suppress
|
||||
from typing import Any
|
||||
@@ -69,6 +70,7 @@ from ..widgets import (
|
||||
page_total,
|
||||
run_async,
|
||||
)
|
||||
from .local_audio_queue import LocalAudioQueueDialog
|
||||
from .prescription_ai import can_open_diagnosis_ai_report, present_diagnosis_ai_report
|
||||
|
||||
_PHONE_PERMISSION = "tcm.diagnosis/phonePlain"
|
||||
@@ -747,6 +749,7 @@ class DiagnosisDialog(QDialog):
|
||||
"""
|
||||
|
||||
saved = Signal()
|
||||
_local_audio_upload_completed = Signal(int, int)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -841,6 +844,10 @@ class DiagnosisDialog(QDialog):
|
||||
self._recording_players: list[RecordingPlayerDialog] = []
|
||||
self._inline_recording_cells: list[RecordingPlaybackCell] = []
|
||||
self._last_order_detail_dialog: QDialog | None = None
|
||||
self._local_audio_dialog: LocalAudioQueueDialog | None = None
|
||||
self._local_audio_upload_manager: Any = None
|
||||
self._local_audio_upload_listener: Any = None
|
||||
self._video_reload_pending = False
|
||||
self._orders_page = 1
|
||||
self._orders_page_size = 10
|
||||
self._orders_total = 0
|
||||
@@ -868,6 +875,10 @@ class DiagnosisDialog(QDialog):
|
||||
self._daily_panels: list[DailyRecordPanel] = []
|
||||
self._owner = None
|
||||
self._owner_filter_installed = False
|
||||
self._local_audio_upload_completed.connect(
|
||||
self._local_audio_upload_succeeded,
|
||||
type=Qt.ConnectionType.QueuedConnection,
|
||||
)
|
||||
|
||||
self.setObjectName("DiagnosisDialogRoot")
|
||||
self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.FramelessWindowHint)
|
||||
@@ -1433,6 +1444,11 @@ class DiagnosisDialog(QDialog):
|
||||
hint.setWordWrap(True)
|
||||
toolbar.addWidget(hint, 1)
|
||||
toolbar.addStretch(1)
|
||||
self.local_audio_queue_button = QPushButton("本机录音文件")
|
||||
self.local_audio_queue_button.setObjectName("DiagnosisLocalAudioQueueButton")
|
||||
self.local_audio_queue_button.setAccessibleName("查看本机录音文件及上传状态")
|
||||
self.local_audio_queue_button.clicked.connect(self._open_local_audio_queue)
|
||||
toolbar.addWidget(self.local_audio_queue_button)
|
||||
self.video_upload_button = QPushButton("上传本地回放")
|
||||
self.video_upload_button.setProperty("variant", "primary")
|
||||
self.video_upload_button.clicked.connect(
|
||||
@@ -1556,10 +1572,10 @@ class DiagnosisDialog(QDialog):
|
||||
),
|
||||
"video": (
|
||||
("录制回放", 440),
|
||||
("房间号", 180),
|
||||
("开始时间", 170),
|
||||
("结束时间", 170),
|
||||
("通话类型", 100),
|
||||
("房间号", 180),
|
||||
("时长", 110),
|
||||
("状态", 90),
|
||||
("录制 / 文字", 120),
|
||||
@@ -1695,6 +1711,10 @@ class DiagnosisDialog(QDialog):
|
||||
)
|
||||
self.prescribe_button.setVisible(self._editable and self._can_prescribe)
|
||||
self.video_upload_button.setVisible(self._editable and self._can_video_upload)
|
||||
self.local_audio_queue_button.setVisible(self._can_video_upload)
|
||||
self.local_audio_queue_button.setEnabled(
|
||||
self._diagnosis_id > 0 and self._can_video_upload
|
||||
)
|
||||
offset_visible = self._editable and self._can_offset
|
||||
self.order_offset.setVisible(offset_visible)
|
||||
self.order_offset_save.setVisible(offset_visible)
|
||||
@@ -1914,6 +1934,10 @@ class DiagnosisDialog(QDialog):
|
||||
with suppress(RuntimeError):
|
||||
self._last_order_detail_dialog.close()
|
||||
self._last_order_detail_dialog = None
|
||||
if self._local_audio_dialog is not None:
|
||||
with suppress(RuntimeError):
|
||||
self._local_audio_dialog.close()
|
||||
self._local_audio_dialog = None
|
||||
self._diagnosis_id = int(diagnosis_id)
|
||||
self._patient_id = 0
|
||||
self._editable = bool(
|
||||
@@ -1939,6 +1963,7 @@ class DiagnosisDialog(QDialog):
|
||||
self._tab_generations[key] += 1
|
||||
self._loaded_tabs.clear()
|
||||
self._loading_tabs.clear()
|
||||
self._video_reload_pending = False
|
||||
self._daily_todo_status = None
|
||||
self._orders_page = 1
|
||||
self._orders_total = 0
|
||||
@@ -2208,6 +2233,8 @@ class DiagnosisDialog(QDialog):
|
||||
self._ensure_tab_loaded(self._current_tab_key(), force=True)
|
||||
|
||||
def _invalidate_requests(self) -> None:
|
||||
self._stop_watching_local_audio_uploads()
|
||||
self._video_reload_pending = False
|
||||
self._generation += 1
|
||||
self._save_generation += 1
|
||||
self._orders_generation += 1
|
||||
@@ -2232,6 +2259,11 @@ class DiagnosisDialog(QDialog):
|
||||
with suppress(RuntimeError):
|
||||
order_dialog.close()
|
||||
self._last_order_detail_dialog = None
|
||||
local_audio_dialog = getattr(self, "_local_audio_dialog", None)
|
||||
if local_audio_dialog is not None:
|
||||
with suppress(RuntimeError):
|
||||
local_audio_dialog.close()
|
||||
self._local_audio_dialog = None
|
||||
if hasattr(self, "readonly_loading"):
|
||||
self.readonly_loading.hide()
|
||||
if hasattr(self, "drawer_loading"):
|
||||
@@ -2474,7 +2506,11 @@ class DiagnosisDialog(QDialog):
|
||||
def _tab_changed(self, _index: int) -> None:
|
||||
self._sync_save_button()
|
||||
if self._authoritative_detail_loaded and not self._standalone_readonly:
|
||||
self._ensure_tab_loaded(self._current_tab_key())
|
||||
key = self._current_tab_key()
|
||||
if key == "video":
|
||||
self._reload_video_records(self._diagnosis_id)
|
||||
else:
|
||||
self._ensure_tab_loaded(key)
|
||||
|
||||
def _load_visible_readonly_sections(self) -> None:
|
||||
permission_map = {key: codes for key, _label, codes in _TAB_DEFINITIONS}
|
||||
@@ -2635,6 +2671,8 @@ class DiagnosisDialog(QDialog):
|
||||
panel.set_messages(rows)
|
||||
if not self._standalone_readonly and self._current_tab_key() == key:
|
||||
self._clear_message()
|
||||
if key == "video":
|
||||
self._flush_video_reload_if_pending(diagnosis_id)
|
||||
|
||||
def _tab_load_error(
|
||||
self,
|
||||
@@ -2650,6 +2688,8 @@ class DiagnosisDialog(QDialog):
|
||||
self._set_tab_error(key, text)
|
||||
if not self._standalone_readonly and self._current_tab_key() == key:
|
||||
self._show_message(text, "danger", action_text="重试")
|
||||
if key == "video":
|
||||
self._flush_video_reload_if_pending(diagnosis_id)
|
||||
|
||||
def _load_daily_range(self, start: str, end: str, *, force: bool = False) -> None:
|
||||
key = "daily"
|
||||
@@ -3116,6 +3156,91 @@ class DiagnosisDialog(QDialog):
|
||||
"video",
|
||||
)
|
||||
|
||||
def _open_local_audio_queue(self) -> None:
|
||||
if self._diagnosis_id <= 0 or not self._can_video_upload:
|
||||
self._show_message("当前账号无本机录音上传权限或接口不可用。", "warning")
|
||||
return
|
||||
current = self._local_audio_dialog
|
||||
if current is not None and current.isVisible():
|
||||
current.raise_()
|
||||
current.activateWindow()
|
||||
return
|
||||
try:
|
||||
dialog = LocalAudioQueueDialog(
|
||||
self.repository,
|
||||
self._diagnosis_id,
|
||||
self,
|
||||
)
|
||||
except (OSError, RuntimeError, sqlite3.Error) as error:
|
||||
self._show_message(f"无法打开本机录音文件:{error}", "danger")
|
||||
return
|
||||
self._local_audio_dialog = dialog
|
||||
opened_diagnosis_id = self._diagnosis_id
|
||||
self._watch_local_audio_uploads(dialog.manager)
|
||||
|
||||
def clear_dialog(_result: int) -> None:
|
||||
if self._local_audio_dialog is dialog:
|
||||
self._local_audio_dialog = None
|
||||
|
||||
dialog.finished.connect(clear_dialog)
|
||||
dialog.open()
|
||||
# Opening the queue commonly follows a background upload that completed
|
||||
# before this dialog existed, so also refresh the server-backed rows now.
|
||||
self._reload_video_records(opened_diagnosis_id)
|
||||
|
||||
def _local_audio_upload_succeeded(
|
||||
self,
|
||||
diagnosis_id: int,
|
||||
_call_record_id: int,
|
||||
) -> None:
|
||||
if self._local_audio_upload_manager is None:
|
||||
return
|
||||
self._reload_video_records(diagnosis_id)
|
||||
|
||||
def _reload_video_records(self, diagnosis_id: int) -> None:
|
||||
if int(diagnosis_id) != self._diagnosis_id:
|
||||
return
|
||||
if "video" in self._loading_tabs:
|
||||
self._video_reload_pending = True
|
||||
return
|
||||
self._video_reload_pending = False
|
||||
self._loaded_tabs.discard("video")
|
||||
self._ensure_tab_loaded("video", force=True)
|
||||
|
||||
def _watch_local_audio_uploads(self, manager: Any) -> None:
|
||||
if self._local_audio_upload_manager is manager:
|
||||
return
|
||||
self._stop_watching_local_audio_uploads()
|
||||
|
||||
def notify(record: Any) -> None:
|
||||
with suppress(RuntimeError):
|
||||
self._local_audio_upload_completed.emit(
|
||||
int(record.diagnosis_id),
|
||||
int(record.call_record_id or 0),
|
||||
)
|
||||
|
||||
manager.add_upload_listener(notify)
|
||||
self._local_audio_upload_manager = manager
|
||||
self._local_audio_upload_listener = notify
|
||||
|
||||
def _stop_watching_local_audio_uploads(self) -> None:
|
||||
manager = self._local_audio_upload_manager
|
||||
listener = self._local_audio_upload_listener
|
||||
self._local_audio_upload_manager = None
|
||||
self._local_audio_upload_listener = None
|
||||
if manager is not None and listener is not None:
|
||||
with suppress(Exception):
|
||||
manager.remove_upload_listener(listener)
|
||||
|
||||
def _flush_video_reload_if_pending(self, diagnosis_id: int) -> None:
|
||||
if not self._video_reload_pending or diagnosis_id != self._diagnosis_id:
|
||||
return
|
||||
self._video_reload_pending = False
|
||||
QTimer.singleShot(
|
||||
0,
|
||||
lambda expected_id=diagnosis_id: self._reload_video_records(expected_id),
|
||||
)
|
||||
|
||||
def _sync_chat_archive(self) -> None:
|
||||
if not self._can_chat_sync or self._diagnosis_id <= 0:
|
||||
self._show_message("当前账号无聊天归档同步权限或接口不可用。", "warning")
|
||||
@@ -3616,6 +3741,7 @@ class DiagnosisDialog(QDialog):
|
||||
self._stop_inline_recordings()
|
||||
matrix: list[tuple[Any, ...]] = []
|
||||
row_urls: list[list[str]] = []
|
||||
row_audio_urls: list[list[str]] = []
|
||||
record_ids: list[int] = []
|
||||
transcripts: list[str] = []
|
||||
for row in rows:
|
||||
@@ -3629,6 +3755,22 @@ class DiagnosisDialog(QDialog):
|
||||
if url and url not in normalized:
|
||||
normalized.append(url)
|
||||
row_urls.append(normalized)
|
||||
raw_audio_urls = first_value(
|
||||
row,
|
||||
"local_audio_urls_list",
|
||||
"local_audio_urls",
|
||||
default=[],
|
||||
) or []
|
||||
if isinstance(raw_audio_urls, str) or not isinstance(
|
||||
raw_audio_urls, Sequence
|
||||
):
|
||||
raw_audio_urls = [raw_audio_urls]
|
||||
normalized_audio: list[str] = []
|
||||
for candidate in raw_audio_urls:
|
||||
url = str(candidate or "").strip()
|
||||
if url and url not in normalized_audio:
|
||||
normalized_audio.append(url)
|
||||
row_audio_urls.append(normalized_audio)
|
||||
record_ids.append(_int(first_value(row, "id", "call_record_id"), 0))
|
||||
transcript = self._call_transcript_text(row)
|
||||
transcripts.append(transcript)
|
||||
@@ -3651,22 +3793,41 @@ class DiagnosisDialog(QDialog):
|
||||
recording_status = first_value(
|
||||
row, "recording_status_text", "record_status_text", "record_status"
|
||||
)
|
||||
local_audio_status = first_value(
|
||||
row,
|
||||
"local_audio_status_text",
|
||||
default="本机录音已保存" if normalized_audio else "无本机录音",
|
||||
)
|
||||
transcript_status = first_value(
|
||||
row,
|
||||
"transcription_status_text",
|
||||
"transcript_status_text",
|
||||
default="文字已生成" if transcript else "未生成文字",
|
||||
)
|
||||
room_id = str(
|
||||
first_value(
|
||||
row,
|
||||
"room_id_text",
|
||||
"room_id",
|
||||
"room_no",
|
||||
default="",
|
||||
)
|
||||
or ""
|
||||
).strip()
|
||||
matrix.append(
|
||||
(
|
||||
"" if normalized else "暂无录制回放",
|
||||
room_id or "历史记录未保存",
|
||||
first_value(row, "start_time_text", "start_time"),
|
||||
first_value(row, "end_time_text", "end_time"),
|
||||
call_type,
|
||||
first_value(row, "room_id", "room_no"),
|
||||
first_value(row, "duration_text", "duration"),
|
||||
status,
|
||||
f"{display_text(recording_status)}\n{display_text(transcript_status)}",
|
||||
(
|
||||
f"云端视频:{display_text(recording_status)}\n"
|
||||
f"本机录音:{display_text(local_audio_status)}\n"
|
||||
f"转写文字:{display_text(transcript_status)}"
|
||||
),
|
||||
"",
|
||||
)
|
||||
)
|
||||
@@ -3692,6 +3853,19 @@ class DiagnosisDialog(QDialog):
|
||||
item.setText("")
|
||||
call_record_id = record_ids[row_index]
|
||||
actions: list[QPushButton] = []
|
||||
audio_urls = row_audio_urls[row_index]
|
||||
if audio_urls and call_record_id > 0:
|
||||
play_audio = self._action_button(
|
||||
"播放录音", f"播放通话记录 #{call_record_id} 的本机混音录音"
|
||||
)
|
||||
play_audio.setObjectName("DiagnosisLocalAudioPlayback")
|
||||
play_audio.setProperty("callRecordId", call_record_id)
|
||||
play_audio.clicked.connect(
|
||||
lambda _checked=False, target=audio_urls[0]: self._open_recording_player(
|
||||
target
|
||||
)
|
||||
)
|
||||
actions.append(play_audio)
|
||||
transcript = transcripts[row_index]
|
||||
if transcript and call_record_id > 0:
|
||||
view_transcript = self._action_button(
|
||||
|
||||
Reference in New Issue
Block a user