180 lines
9.3 KiB
Python
180 lines
9.3 KiB
Python
from pathlib import Path
|
|
p=Path(r'C:\kefu\wechat_rpa\wechat_gui_qt.py')
|
|
s=p.read_text(encoding='utf-8-sig')
|
|
start=s.index('class PatientBindingDialog('); end=s.index('class ConsoleBridge(',start)
|
|
c=s[start:end]
|
|
def replace(old,new):
|
|
global c
|
|
assert c.count(old)==1, (old[:80],c.count(old))
|
|
c=c.replace(old,new,1)
|
|
replace(' operationFinished = Signal(object)\n',' operationFinished = Signal(object)\n reauthenticationFinished = Signal(object)\n')
|
|
replace(' self.changed = False\n',' self.changed = False\n self._patient_session_expired = False\n self._busy = False\n')
|
|
replace(' layout.addWidget(self.hint_label)\n',''' layout.addWidget(self.hint_label)
|
|
self.reauthenticate_button = QPushButton("重新验证 ZYT 登录")
|
|
self.reauthenticate_button.clicked.connect(self._reauthenticate)
|
|
self.reauthenticate_button.hide()
|
|
layout.addWidget(self.reauthenticate_button)
|
|
''')
|
|
replace(' self.operationFinished.connect(self._operation_finished)\n',' self.operationFinished.connect(self._operation_finished)\n self.reauthenticationFinished.connect(self._reauthentication_finished)\n')
|
|
replace(''' self.search_input.setEnabled(self.can_search and not busy)
|
|
self.search_button.setEnabled(self.can_search and not busy)
|
|
self.bind_button.setEnabled(self.can_bind and not busy)
|
|
''',''' self._busy = busy
|
|
query_ready = not busy and not self._patient_session_expired
|
|
self.search_input.setEnabled(self.can_search and not busy)
|
|
self.search_button.setEnabled(self.can_search and query_ready)
|
|
self.bind_button.setEnabled(self.can_bind and query_ready)
|
|
self.reauthenticate_button.setEnabled(not busy)
|
|
''')
|
|
replace(' def _search(self) -> None:\n',''' def _show_patient_session_expired(self) -> None:
|
|
self._patient_session_expired = True
|
|
self._patients = []
|
|
self.result_table.setRowCount(0)
|
|
self.reauthenticate_button.show()
|
|
self._set_busy(False, "ZYT 患者查询登录已过期,请点击下方按钮重新验证当前账号。"
|
|
"验证后可重新搜索并核对患者,客服监听继续运行。")
|
|
|
|
def _reauthenticate(self) -> None:
|
|
if self._busy:
|
|
return
|
|
import backend_client
|
|
|
|
account = str(backend_client.load_settings().get("zyt_account") or "当前账号")
|
|
password, accepted = QInputDialog.getText(
|
|
self, "重新验证 ZYT 登录",
|
|
f"请输入 ZYT 账号 {account} 的密码:\n仅恢复患者查询登录,客服监听继续运行。",
|
|
QLineEdit.Password,
|
|
)
|
|
if not accepted:
|
|
return
|
|
if not password:
|
|
self.hint_label.setText("请输入当前 ZYT 账号的密码后重试。")
|
|
return
|
|
self._set_busy(True, "正在验证 ZYT 账号并恢复患者查询…")
|
|
person_id = str(self._selected_person().get("id") or "")
|
|
|
|
def work() -> None:
|
|
try:
|
|
backend_client.reauthenticate_patient_session(password)
|
|
context = backend_client.desktop_patient_context(
|
|
self.external_account_id, self.conversation_external_id,
|
|
person_id=person_id,
|
|
)
|
|
payload = {"ok": True, "context": context}
|
|
except Exception as exc:
|
|
payload = {"ok": False, "error": str(exc)}
|
|
try:
|
|
self.reauthenticationFinished.emit(payload)
|
|
except RuntimeError:
|
|
pass
|
|
|
|
threading.Thread(target=work, name="zyt-patient-reauthentication", daemon=True).start()
|
|
|
|
@Slot(object)
|
|
def _reauthentication_finished(self, payload: object) -> None:
|
|
values = dict(payload or {}) if isinstance(payload, dict) else {}
|
|
if not values.get("ok"):
|
|
self._set_busy(False, f"验证失败:{values.get('error') or '请重试'}")
|
|
return
|
|
self.context = dict(values.get("context") or {})
|
|
self.permissions = dict(self.context.get("permissions") or {})
|
|
self.can_search = bool(self.permissions.get("can_search"))
|
|
self.can_bind = bool(self.permissions.get("can_bind"))
|
|
self.can_unbind = bool(self.permissions.get("can_unbind"))
|
|
self.people = list(self.context.get("people") or [])
|
|
self._patient_session_expired = False
|
|
self.reauthenticate_button.hide()
|
|
self._patients = []
|
|
self.result_table.setRowCount(0)
|
|
self._person_changed()
|
|
self._set_busy(False, "ZYT 登录已恢复,请搜索并核对患者后确认绑定。")
|
|
if not self.can_search:
|
|
self.hint_label.setText(str(self.permissions.get("reason") or "当前账号没有患者查询权限。"))
|
|
elif self.search_input.text().strip():
|
|
self._search()
|
|
|
|
def _search(self) -> None:
|
|
if self._busy or self._patient_session_expired:
|
|
return
|
|
''')
|
|
# Escape the newline inside the password prompt's f-string in generated source.
|
|
c=c.replace('的密码:\n仅恢复患者查询登录,客服监听继续运行。",','的密码:\\n仅恢复患者查询登录,客服监听继续运行。",')
|
|
replace(' payload = {"ok": False, "error": str(exc)}\n try:\n self.searchFinished.emit(payload)',''' payload = {"ok": False, "error": str(exc),
|
|
"patient_session_expired": isinstance(exc, backend_client.PatientSessionExpired)}
|
|
try:
|
|
self.searchFinished.emit(payload)''')
|
|
replace(''' if not values.get("ok"):
|
|
self.hint_label.setText(f"查询失败:{values.get('error') or '未知错误'}")
|
|
''',''' if not values.get("ok"):
|
|
if values.get("patient_session_expired"):
|
|
self._show_patient_session_expired()
|
|
return
|
|
self.hint_label.setText(f"查询失败:{values.get('error') or '未知错误'}")
|
|
''')
|
|
replace(' def _bind_selected(self) -> None:\n',' def _bind_selected(self) -> None:\n if self._busy or self._patient_session_expired:\n return\n')
|
|
replace(' payload = {"ok": False, "action": action, "error": str(exc)}',''' payload = {"ok": False, "action": action, "error": str(exc),
|
|
"patient_session_expired": isinstance(exc, backend_client.PatientSessionExpired)}''')
|
|
replace(''' if not values.get("ok"):
|
|
self.hint_label.setText(
|
|
f"操作失败:{values.get('error') or '未知错误'}"
|
|
''',''' if not values.get("ok"):
|
|
if values.get("patient_session_expired"):
|
|
self._show_patient_session_expired()
|
|
return
|
|
self.hint_label.setText(
|
|
f"操作失败:{values.get('error') or '未知错误'}"
|
|
''')
|
|
s=s[:start]+c+s[end:]
|
|
s=s.replace('class MainWindow(QMainWindow):\n desktopSessionChecked = Signal(str, object)\n','class MainWindow(QMainWindow):\n desktopSessionChecked = Signal(str, object)\n patientSessionChecked = Signal(object)\n',1)
|
|
marker=' def _check_desktop_session(self) -> None:\n'
|
|
assert s.count(marker)==1
|
|
s=s.replace(marker,''' def _keepalive_patient_session(self) -> None:
|
|
if self._patient_keepalive_running or self._forced_logout_handled:
|
|
return
|
|
self._patient_keepalive_running = True
|
|
|
|
def check() -> None:
|
|
try:
|
|
import backend_client
|
|
|
|
result = backend_client.keepalive_zyt_session()
|
|
except Exception:
|
|
result = {"state": "unreachable"}
|
|
try:
|
|
self.patientSessionChecked.emit(result)
|
|
except RuntimeError:
|
|
pass
|
|
|
|
threading.Thread(target=check, name="zyt-session-keepalive", daemon=True).start()
|
|
|
|
@Slot(object)
|
|
def _patient_session_checked(self, result: object) -> None:
|
|
self._patient_keepalive_running = False
|
|
values = dict(result or {}) if isinstance(result, dict) else {}
|
|
state = str(values.get("state") or "unreachable")
|
|
if state == "skipped":
|
|
return
|
|
previous = self._patient_session_state
|
|
self._patient_session_state = state
|
|
if state == "expired" and previous != state:
|
|
self.append_log("ZYT 患者查询登录已过期,可在绑定患者窗口重新验证;客服监听继续运行。", "warn")
|
|
elif state == "active" and previous == "expired":
|
|
self.append_log("ZYT 患者查询登录已恢复。", "ok")
|
|
|
|
'''+marker,1)
|
|
marker=' self._desktop_session_check_running = False\n self._desktop_session_state = "valid"\n'
|
|
assert s.count(marker)==1
|
|
s=s.replace(marker,''' self._patient_keepalive_running = False
|
|
self._patient_session_state = "unknown"
|
|
self.patientSessionChecked.connect(self._patient_session_checked)
|
|
self.patient_session_timer = QTimer(self)
|
|
self.patient_session_timer.setInterval(30 * 60 * 1000)
|
|
self.patient_session_timer.timeout.connect(self._keepalive_patient_session)
|
|
if "--qt-smoke-test" not in sys.argv:
|
|
self.patient_session_timer.start()
|
|
QTimer.singleShot(5000, self._keepalive_patient_session)
|
|
|
|
'''+marker,1)
|
|
compile(s,str(p),'exec')
|
|
p.write_text(s,encoding='utf-8',newline='\n')
|
|
print('source GUI updated') |