85 lines
3.1 KiB
Python
85 lines
3.1 KiB
Python
"""扫码开票单入口的原子导航工具。二维码必须由任务显式提供。"""
|
||
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"]}
|