"""扫码开票单入口的原子导航工具。二维码必须由任务显式提供。""" from __future__ import annotations import time from pathlib import Path from . import device, vision from .tools import ToolError, observe_screen, tap_normalized REMOTE_QR = "/sdcard/Pictures/autotrain-next-qr.png" def _image(context: dict) -> Path: return Path(observe_screen({}, context)["screenshot"]) def _click(context: dict, label: str) -> dict: target = vision.find_button(_image(context), label) if not target.get("found"): raise ToolError(f"未找到「{label}」按钮") result = tap_normalized({"point": target["point"]}, context) time.sleep(0.8) return result def push_qr(_: dict, context: dict) -> dict: source = Path(str(context.get("qr_image") or "")) if not source.is_file(): raise ToolError("任务未提供可用的 qr_image") device.run(str(context["device_serial"]), ["push", str(source), REMOTE_QR]) context.setdefault("navigation", {})["phase"] = "open_scan" return {"remote_qr": REMOTE_QR} def open_scan(_: dict, context: dict) -> dict: try: result = _click(context, "扫码开票") except ToolError: context.setdefault("navigation", {})["phase"] = "open_orders" return _click(context, "订单") if not vision.find_button(_image(context), "相册").get("found"): raise ToolError("点击扫码开票后未进入扫码界面") context.setdefault("navigation", {})["phase"] = "open_album" return result def open_orders(_: dict, context: dict) -> dict: result = _click(context, "电子发票") context.setdefault("navigation", {})["phase"] = "open_scan" return result def open_album(_: dict, context: dict) -> dict: result = _click(context, "相册") context.setdefault("navigation", {})["phase"] = "select_qr" return result def select_qr(_: dict, context: dict) -> dict: prompt = "在相册截图中找到文件 autotrain-next-qr.png 的二维码缩略图。只返回 JSON:{\"found\":true,\"center\":[500,500]},center 是0-1000归一化坐标;找不到则 found=false。" target = vision.ask(_image(context), prompt) center = target.get("center") or [] if not target.get("found") or len(center) != 2: raise ToolError("相册未找到任务二维码缩略图") point = [float(center[0]) / 1000, float(center[1]) / 1000] if not all(0 <= value <= 1 for value in point): raise ToolError("二维码缩略图坐标无效") result = tap_normalized({"point": point}, context) context.setdefault("navigation", {})["phase"] = "wait_list" return result def wait_list(_: dict, context: dict) -> dict: nav = context.setdefault("navigation", {}) nav["wait_attempts"] = int(nav.get("wait_attempts", 0)) + 1 time.sleep(1) page = vision.detect_page(_image(context)).get("page", "other") if page == "list": nav["phase"] = "done" return {"list_ready": True} if nav["wait_attempts"] >= 5: raise ToolError(f"扫码后未进入列表页,当前页面={page}") return {"list_ready": False, "page": page, "attempt": nav["wait_attempts"]}