Files
kefu/deploy/review-visibility-20260916/finish_qt_handoff.py
T
2026-09-21 10:34:06 +08:00

68 lines
3.8 KiB
Python

"""Wire explicit manual handoff for uncertain delivery without resending."""
import ast
import os
from pathlib import Path
METHOD=''' def _handoff_queue_tasks(self, keys) -> None:
requested = list(dict.fromkeys(str(key or "").strip() for key in (keys or []) if str(key or "").strip()))
if not requested:
return
pending = getattr(self.queue_page, "pending_states", {}) or {}
uncertain = any(task_review_state(pending.get(key))["deliveryUncertain"] for key in requested)
if uncertain:
answer = QMessageBox.question(
self, "核对发送结果后转人工",
"这条回复可能已经发出。请先在企业微信的原会话核对发送结果。\\n\\n"
"继续后将从自动队列移出,由人工跟进;保留发送记录,不会自动重发,也不会标记为已确认发送。\\n\\n"
"已核对,确认转人工处理?",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
QMessageBox.StandardButton.No,
)
if answer != QMessageBox.StandardButton.Yes:
return
thread = getattr(self, "_thread", None)
try:
if thread is not None and thread.is_alive():
handoff = getattr(thread, "handoff_pending_tasks", None)
result = handoff(requested) if handoff else thread.cancel_pending_tasks(requested)
else:
from gui_runtime import handoff_pending_reply_file
QUEUE_PATH
result = handoff_pending_reply_file(requested, str(path))
except Exception as exc:
QMessageBox.warning(self, "转人工失败", str(exc))
return
if result.get("error"):
QMessageBox.warning(self, "转人工失败", str(result["error"]))
accepted = set(result.get("handed_off") or result.get("deleted") or [])
scheduled = set(result.get("scheduled") or [])
if accepted:
self.append_log(f"已将 {len(accepted)} 条任务转交人工,保留发送记录,不再自动重发。", "notify")
if scheduled:
self.append_log(f"已登记 {len(scheduled)} 条人工接管操作,监听线程就绪后执行。", "notify")
if result.get("protected"):
QMessageBox.information(self, "暂不能转人工", "任务正在发送或属于其他账号,请等待发送结束并在对应账号下处理。")
self.queue_page.refresh_data()
self._schedule_console_push(urgent=True)
'''
for root in (Path('C:/kefu/wechat_rpa'),Path('C:/wechat_rpa')):
path=root/'wechat_gui_qt.py';source=path.read_text(encoding='utf-8')
tree=ast.parse(source);cls=next(n for n in tree.body if isinstance(n,ast.ClassDef) and n.name=='MainWindow')
node=next(n for n in cls.body if isinstance(n,ast.FunctionDef) and n.name=='_handoff_queue_tasks')
lines=source.splitlines(keepends=True)
queue_path='path = queue_path_for_transport(self.runtime_settings.get("reply_transport", VISUAL), root=SCRIPT_DIR)' if (root/'reply_transport.py').exists() else 'path = SCRIPT_DIR / "pending_replies.json"'
source=''.join(lines[:node.lineno-1])+METHOD.replace('QUEUE_PATH',queue_path).rstrip()+'\n'+''.join(lines[node.end_lineno:])
# Do not retain explicit approvals if an asynchronous protocol check failed.
old=''' QTimer.singleShot(0, self.start_monitoring)
def _export_protocol_report'''
new=''' QTimer.singleShot(0, self.start_monitoring)
else:
self._deferred_review_approvals = []
def _export_protocol_report'''
source=source.replace(old,new,1)
compile(source,str(path),'exec')
temporary=path.with_name(path.name+'.review-patch.tmp');temporary.write_text(source,encoding='utf-8');os.replace(temporary,path)
print(root)