自动扫码.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. import tkinter as tk
  2. from tkinter import ttk, scrolledtext, messagebox, filedialog
  3. import subprocess
  4. import threading
  5. import json
  6. import os
  7. import time
  8. import random
  9. import requests
  10. from datetime import datetime
  11. import win32gui
  12. import win32con
  13. import win32api
  14. import tkinter as tk
  15. from PIL import Image, ImageTk
  16. def drag_in_emulator(manager_path, emu_index, x, y1, y2, duration=400):
  17. """
  18. 在模拟器中从 (x, y1) 拖拽到 (x, y2)
  19. """
  20. # 获取adb端口
  21. cmd = [manager_path, "info", "-v", str(emu_index)]
  22. result = subprocess.run(cmd, capture_output=True, text=True, encoding='utf-8')
  23. if result.returncode != 0:
  24. return False
  25. try:
  26. data = json.loads(result.stdout)
  27. adb_port = data.get('adb_port')
  28. if not adb_port:
  29. return False
  30. except:
  31. return False
  32. # 连接adb
  33. target_device = f"127.0.0.1:{adb_port}"
  34. subprocess.run(f"adb connect {target_device}", shell=True, capture_output=True)
  35. time.sleep(0.3)
  36. # 执行滑动
  37. cmd = f"adb -s {target_device} shell input swipe {x} {y1} {x} {y2} {duration}"
  38. result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
  39. return result.returncode == 0
  40. def input_text_to_emulator(manager_path, emu_index, text):
  41. """向模拟器输入文本"""
  42. # 获取adb端口
  43. cmd = [manager_path, "info", "-v", str(emu_index)]
  44. result = subprocess.run(cmd, capture_output=True, text=True, encoding='utf-8')
  45. if result.returncode != 0:
  46. return False
  47. try:
  48. data = json.loads(result.stdout)
  49. adb_port = data.get('adb_port')
  50. if not adb_port:
  51. return False
  52. except:
  53. return False
  54. target_device = f"127.0.0.1:{adb_port}"
  55. subprocess.run(f"adb connect {target_device}", shell=True, capture_output=True)
  56. # 先删除
  57. subprocess.run(f"adb -s {target_device} shell input keyevent KEYCODE_DEL", shell=True)
  58. # 输入文本
  59. subprocess.run(f"adb -s {target_device} shell input text \"{text}\"", shell=True)
  60. return True
  61. def get_emulator_pixel_color(manager_path, emu_index, x, y):
  62. """
  63. 获取模拟器指定坐标的颜色
  64. Args:
  65. manager_path: MuMuManager.exe路径
  66. emu_index: 模拟器索引
  67. x, y: 坐标
  68. Returns:
  69. 颜色代码,如 "#FFFFFF",失败返回 None
  70. """
  71. # 获取adb端口
  72. cmd = [manager_path, "info", "-v", str(emu_index)]
  73. result = subprocess.run(cmd, capture_output=True, text=True, encoding='utf-8')
  74. if result.returncode != 0:
  75. return None
  76. try:
  77. data = json.loads(result.stdout)
  78. adb_port = data.get('adb_port')
  79. if not adb_port:
  80. return None
  81. except:
  82. return None
  83. # 连接adb
  84. target_device = f"127.0.0.1:{adb_port}"
  85. subprocess.run(f"adb connect {target_device}", shell=True, capture_output=True)
  86. time.sleep(0.3)
  87. # 截图并获取颜色
  88. temp_file = f"temp_screenshot_{emu_index}.png"
  89. subprocess.run(f"adb -s {target_device} exec-out screencap -p > {temp_file}", shell=True)
  90. time.sleep(0.3)
  91. try:
  92. from PIL import Image
  93. img = Image.open(temp_file)
  94. pixel = img.getpixel((x, y))
  95. img.close()
  96. # 转换为十六进制颜色
  97. if isinstance(pixel, tuple):
  98. r, g, b = pixel[0], pixel[1], pixel[2]
  99. else:
  100. r = g = b = pixel
  101. color = f"#{r:02X}{g:02X}{b:02X}"
  102. return color
  103. except Exception as e:
  104. return None
  105. finally:
  106. import os
  107. if os.path.exists(temp_file):
  108. os.remove(temp_file)
  109. def show_image_at_position(image_path, x, y, width=250, height=250):
  110. """
  111. 在指定位置创建窗口显示图片并激活
  112. """
  113. # 创建窗口
  114. window = tk.Toplevel()
  115. window.title("图片显示")
  116. # 设置窗口位置和大小
  117. window.geometry(f"{width}x{height}+{x}+{y}")
  118. # 加载图片
  119. image = Image.open(image_path)
  120. image = image.resize((width, height), Image.Resampling.LANCZOS)
  121. photo = ImageTk.PhotoImage(image)
  122. # 显示图片
  123. label = tk.Label(window, image=photo)
  124. label.image = photo
  125. label.pack(fill=tk.BOTH, expand=True)
  126. # 刷新窗口
  127. window.update()
  128. # 获取窗口句柄并激活
  129. hwnd = win32gui.FindWindow(None, "图片显示")
  130. if hwnd:
  131. win32gui.SetForegroundWindow(hwnd)
  132. return window
  133. def click_screen(x, y):
  134. """
  135. 在屏幕坐标(x, y)处点击鼠标左键
  136. """
  137. # 移动鼠标到指定位置
  138. win32api.SetCursorPos((x, y))
  139. # 按下左键
  140. win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, x, y, 0, 0)
  141. # 抬起左键
  142. win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, x, y, 0, 0)
  143. def activate_window_and_get_position(window_title):
  144. """
  145. 激活窗口并返回左上角坐标
  146. """
  147. # 查找窗口
  148. hwnd = win32gui.FindWindow(None, window_title)
  149. if hwnd == 0:
  150. print(f"未找到窗口: {window_title}")
  151. return None, None
  152. # 如果窗口最小化,恢复它
  153. if win32gui.IsIconic(hwnd):
  154. win32gui.ShowWindow(hwnd, win32con.SW_RESTORE)
  155. # 激活窗口
  156. win32gui.SetForegroundWindow(hwnd)
  157. # 获取窗口位置
  158. rect = win32gui.GetWindowRect(hwnd)
  159. x = rect[0]
  160. y = rect[1]
  161. return x, y
  162. class MuMuEmulatorManager:
  163. def __init__(self, manager_path):
  164. self.manager_path = manager_path
  165. def get_adb_port(self, index, log_callback=None):
  166. """获取指定模拟器的 ADB 端口"""
  167. cmd = [self.manager_path, "info", "-v", str(index)]
  168. result = subprocess.run(cmd, capture_output=True, text=True, encoding='utf-8')
  169. if result.returncode == 0:
  170. try:
  171. data = json.loads(result.stdout)
  172. adb_port = data.get('adb_port')
  173. if adb_port is not None:
  174. if log_callback:
  175. log_callback(f"✅ 模拟器 {index} ADB端口: {adb_port}")
  176. return adb_port
  177. except:
  178. pass
  179. return None
  180. def tap(self, index, x, y, log_callback=None):
  181. """点击坐标"""
  182. adb_port = self.get_adb_port(index, log_callback)
  183. if not adb_port:
  184. if log_callback:
  185. log_callback(f"❌ 无法获取模拟器 {index} 的ADB端口")
  186. return False
  187. target_device = f"127.0.0.1:{adb_port}"
  188. # 连接ADB
  189. subprocess.run(f"adb connect {target_device}", shell=True, capture_output=True)
  190. time.sleep(0.5)
  191. # 执行点击
  192. cmd = f"adb -s {target_device} shell input tap {x} {y}"
  193. result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
  194. if result.returncode == 0:
  195. if log_callback:
  196. log_callback(f"✅ 点击坐标 ({x}, {y}) 成功")
  197. return True
  198. else:
  199. if log_callback:
  200. log_callback(f"❌ 点击失败: {result.stderr}")
  201. return False
  202. def get_emulator_list(self):
  203. """获取所有模拟器列表"""
  204. cmd = [self.manager_path, "info", "-v", "all"]
  205. result = subprocess.run(cmd, capture_output=True, text=True, encoding='utf-8')
  206. if result.returncode != 0:
  207. return []
  208. try:
  209. # 清理输出(可能包含非JSON内容)
  210. output = result.stdout.strip()
  211. json_start = output.find('{')
  212. if json_start != -1:
  213. output = output[json_start:]
  214. data = json.loads(output)
  215. emulators = []
  216. for key, value in data.items():
  217. if isinstance(value, dict):
  218. value['index'] = key
  219. # 只返回运行中的模拟器
  220. if value.get('is_process_started', False):
  221. emulators.append(value)
  222. return emulators
  223. except json.JSONDecodeError:
  224. return []
  225. class SimpleMuMuManager:
  226. def __init__(self, root):
  227. self.root = root
  228. self.root.title("MuMu模拟器管理工具")
  229. self.root.geometry("650x450")
  230. # 配置文件
  231. self.config_file = "mumu_config.json"
  232. self.mumu_manager_path = None
  233. self.emulators = []
  234. # 创建界面
  235. self.create_widgets()
  236. # 加载配置
  237. self.load_config()
  238. # 如果路径存在,自动刷新
  239. if self.mumu_manager_path and os.path.exists(self.mumu_manager_path):
  240. self.refresh_emulators()
  241. def create_widgets(self):
  242. # 主框架
  243. main_frame = ttk.Frame(self.root, padding="10")
  244. main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
  245. # 配置区域
  246. config_frame = ttk.LabelFrame(main_frame, text="MuMuManager配置", padding="10")
  247. config_frame.grid(row=0, column=0, sticky=(tk.W, tk.E), pady=5)
  248. self.path_var = tk.StringVar()
  249. self.path_entry = ttk.Entry(config_frame, textvariable=self.path_var, width=55)
  250. self.path_entry.grid(row=0, column=1, padx=5)
  251. self.path_entry.bind('<FocusOut>', self.on_path_changed)
  252. browse_btn = ttk.Button(config_frame, text="浏览", command=self.browse_mumu_manager)
  253. browse_btn.grid(row=0, column=2, padx=5)
  254. refresh_btn = ttk.Button(config_frame, text="刷新列表", command=self.refresh_emulators)
  255. refresh_btn.grid(row=0, column=3, padx=5)
  256. # 模拟器选择区域 - 一行两个
  257. selector_frame = ttk.Frame(main_frame)
  258. selector_frame.grid(row=1, column=0, pady=20)
  259. # 发货手机
  260. send_frame = ttk.LabelFrame(selector_frame, text="发货手机", padding="10")
  261. send_frame.grid(row=0, column=0, padx=10)
  262. self.send_var = tk.StringVar()
  263. self.send_combo = ttk.Combobox(send_frame, textvariable=self.send_var, width=35, state="readonly")
  264. self.send_combo.grid(row=0, column=0)
  265. # 收货手机
  266. receive_frame = ttk.LabelFrame(selector_frame, text="收货手机", padding="10")
  267. receive_frame.grid(row=0, column=1, padx=10)
  268. self.receive_var = tk.StringVar()
  269. self.receive_combo = ttk.Combobox(receive_frame, textvariable=self.receive_var, width=35, state="readonly")
  270. self.receive_combo.grid(row=0, column=0)
  271. # 日志区域
  272. log_frame = ttk.LabelFrame(main_frame, text="日志", padding="10")
  273. log_frame.grid(row=2, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), pady=10)
  274. self.log_text = scrolledtext.ScrolledText(log_frame, width=75, height=15, wrap=tk.WORD)
  275. self.log_text.grid(row=0, column=0)
  276. # 测试按钮
  277. # test_btn = ttk.Button(main_frame, text="测试发货", command=self.test_click, width=20)
  278. # test_btn.grid(row=3, column=0, pady=1)
  279. test_btn2 = ttk.Button(main_frame, text="测试收货", command=self.test_click2, width=20)
  280. test_btn2.grid(row=3, column=0, pady=1)
  281. # 配置权重
  282. self.root.columnconfigure(0, weight=1)
  283. self.root.rowconfigure(0, weight=1)
  284. main_frame.columnconfigure(0, weight=1)
  285. main_frame.rowconfigure(2, weight=1)
  286. log_frame.columnconfigure(0, weight=1)
  287. log_frame.rowconfigure(0, weight=1)
  288. def browse_mumu_manager(self):
  289. """浏览选择MuMuManager.exe"""
  290. file_path = filedialog.askopenfilename(
  291. title="选择MuMuManager.exe",
  292. filetypes=[("Executable files", "*.exe"), ("All files", "*.*")]
  293. )
  294. if file_path:
  295. self.path_var.set(file_path)
  296. self.on_path_changed()
  297. def on_path_changed(self, event=None):
  298. """路径改变时自动保存并刷新"""
  299. new_path = self.path_var.get()
  300. if new_path and os.path.exists(new_path):
  301. self.mumu_manager_path = new_path
  302. self.save_config()
  303. self.log_message("配置已自动保存")
  304. self.refresh_emulators()
  305. elif new_path:
  306. self.log_message(f"路径不存在: {new_path}", "WARNING")
  307. def save_config(self):
  308. """保存配置"""
  309. config = {'mumu_manager_path': self.mumu_manager_path}
  310. try:
  311. with open(self.config_file, 'w', encoding='utf-8') as f:
  312. json.dump(config, f, indent=4)
  313. except Exception as e:
  314. self.log_message(f"保存配置失败: {e}", "ERROR")
  315. def load_config(self):
  316. """加载配置"""
  317. if os.path.exists(self.config_file):
  318. try:
  319. with open(self.config_file, 'r', encoding='utf-8') as f:
  320. config = json.load(f)
  321. path = config.get('mumu_manager_path')
  322. if path and os.path.exists(path):
  323. self.mumu_manager_path = path
  324. self.path_var.set(path)
  325. self.log_message(f"已加载配置: {path}")
  326. elif path:
  327. self.log_message(f"配置路径不存在: {path}", "WARNING")
  328. except Exception as e:
  329. self.log_message(f"加载配置失败: {e}", "ERROR")
  330. def log_message(self, message, level="INFO"):
  331. """添加日志"""
  332. timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  333. log_entry = f"[{timestamp}] [{level}] {message}\n"
  334. self.log_text.insert(tk.END, log_entry)
  335. self.log_text.see(tk.END)
  336. self.root.update()
  337. def refresh_emulators(self):
  338. """刷新模拟器列表"""
  339. if not self.mumu_manager_path or not os.path.exists(self.mumu_manager_path):
  340. self.log_message("请先设置正确的 MuMuManager.exe 路径", "WARNING")
  341. return
  342. self.log_message("正在获取模拟器列表...")
  343. try:
  344. manager = MuMuEmulatorManager(self.mumu_manager_path)
  345. self.emulators = manager.get_emulator_list()
  346. if not self.emulators:
  347. self.log_message("未发现运行中的模拟器,请确保 MuMu 模拟器已启动", "WARNING")
  348. self.send_combo['values'] = []
  349. self.receive_combo['values'] = []
  350. return
  351. # 构建显示名称列表
  352. emulator_names = []
  353. for emu in self.emulators:
  354. name = emu.get('name', f"模拟器_{emu.get('index')}")
  355. display_name = f"{name} (索引:{emu.get('index')})"
  356. emulator_names.append(display_name)
  357. self.log_message(f"发现模拟器: {display_name}")
  358. # 更新下拉框
  359. self.send_combo['values'] = emulator_names
  360. self.receive_combo['values'] = emulator_names
  361. self.log_message(f"✅ 已加载 {len(self.emulators)} 个运行中的模拟器")
  362. except Exception as e:
  363. self.log_message(f"获取模拟器列表失败: {e}", "ERROR")
  364. def get_emulator_index(self, display_name):
  365. """从显示名称获取模拟器索引"""
  366. if not display_name:
  367. return None
  368. # 提取索引,格式如 "名称 (索引:0)"
  369. import re
  370. match = re.search(r'索引:(\d+)', display_name)
  371. if match:
  372. return match.group(1)
  373. return None
  374. def test_click(self):
  375. url = "https://task.port.run/acquire/bdxkjzc"
  376. payload = ""
  377. headers = {
  378. "Content-Type": "application/json",
  379. "Accept": "*/*",
  380. "Accept-Encoding": "gzip, deflate, br",
  381. "User-Agent": "PostmanRuntime-ApipostRuntime/1.1.0",
  382. "Connection": "keep-alive"
  383. }
  384. response = requests.request("GET", url, data=payload, headers=headers)
  385. print(response.text)
  386. repData = json.loads(response.text)
  387. if ("task" in repData and "content" in repData['task']):
  388. """测试点击"""
  389. send_selection = self.send_var.get()
  390. if not send_selection:
  391. self.log_message("请选择发货手机模拟器", "ERROR")
  392. messagebox.showwarning("警告", "请选择发货手机模拟器")
  393. return
  394. emu_index = self.get_emulator_index(send_selection)
  395. if not emu_index:
  396. self.log_message("无法获取模拟器索引", "ERROR")
  397. return
  398. # 在新线程中执行点击
  399. thread = threading.Thread(target=self.perform_click, args=(emu_index, send_selection.split(" (")[0], repData['task']["content"]))
  400. thread.daemon = True
  401. thread.start()
  402. else:
  403. self.log_message("未获取到有效任务数据", "ERROR")
  404. messagebox.showerror("错误", "未获取到有效任务数据")
  405. def test_click2(self):
  406. url = "https://task.port.run/acquire/bdxkjxc"
  407. payload = ""
  408. headers = {
  409. "Content-Type": "application/json",
  410. "Accept": "*/*",
  411. "Accept-Encoding": "gzip, deflate, br",
  412. "User-Agent": "PostmanRuntime-ApipostRuntime/1.1.0",
  413. "Connection": "keep-alive"
  414. }
  415. response = requests.request("GET", url, data=payload, headers=headers)
  416. print(response.text)
  417. repData = json.loads(response.text)
  418. if ("task" in repData and "content" in repData['task']):
  419. """测试点击"""
  420. receive_selection = self.receive_var.get()
  421. if not receive_selection:
  422. self.log_message("请选择收货手机模拟器", "ERROR")
  423. messagebox.showwarning("警告", "请选择收货手机模拟器")
  424. return
  425. emu_index = self.get_emulator_index(receive_selection)
  426. if not emu_index:
  427. self.log_message("无法获取模拟器索引", "ERROR")
  428. return
  429. # 在新线程中执行点击
  430. thread = threading.Thread(target=self.perform_click2, args=(emu_index, receive_selection.split(" (")[0], repData['task']["content"]))
  431. thread.daemon = True
  432. thread.start()
  433. else:
  434. self.log_message("未获取到有效任务数据", "ERROR")
  435. messagebox.showerror("错误", "未获取到有效任务数据")
  436. def perform_click(self, emu_index, window_title, content):
  437. """执行点击操作"""
  438. x, y = 508, 252
  439. self.log_message(f"开始在模拟器 {emu_index} 上点击位置 ({x}, {y})")
  440. try:
  441. manager = MuMuEmulatorManager(self.mumu_manager_path)
  442. # 先获取adb端口
  443. adb_port = manager.get_adb_port(emu_index, self.log_message)
  444. if not adb_port:
  445. self.log_message(f"❌ 无法获取模拟器 {emu_index} 的ADB端口", "ERROR")
  446. return
  447. # 执行点击
  448. if manager.tap(emu_index, x, y, self.log_message):
  449. self.log_message(f"✅ 点击成功!模拟器 {emu_index} 位置 ({x}, {y})")
  450. rectX, rectY = activate_window_and_get_position(window_title)
  451. time.sleep(2) # 短暂等待窗口激活
  452. click_screen(rectX + 339, rectY + 576)
  453. time.sleep(1)
  454. showImageBox = show_image_at_position("C:\\Users\\mail\\Downloads\\chepai\\" + content["tableData"][2] + ".png", rectX + 273, rectY + 549 )
  455. # 开始检测是否扫描
  456. color1 = get_emulator_pixel_color(self.mumu_manager_path, emu_index, 523, 1114)
  457. while color1 != "#007AFF": # 假设白色表示未扫描
  458. self.log_message(f"当前颜色: {color1}, 等待扫描完成...")
  459. time.sleep(1)
  460. color1 = get_emulator_pixel_color(self.mumu_manager_path, emu_index, 523, 1114)
  461. # 关闭窗口
  462. showImageBox.destroy()
  463. self.log_message(f"关闭二维码窗口!")
  464. click_screen(rectX + 323, rectY + 718)
  465. time.sleep(1)
  466. drag_in_emulator(self.mumu_manager_path, emu_index, 430, 1046, 980, 400)
  467. time.sleep(0.5)
  468. click_screen(rectX + 650, rectY + 743)
  469. time.sleep(1)
  470. click_screen(rectX + 358, rectY + 1112)
  471. time.sleep(1)
  472. click_screen(rectX + 419, rectY + 760)
  473. else:
  474. self.log_message(f"❌ 点击失败", "ERROR")
  475. except Exception as e:
  476. self.log_message(f"❌ 执行出错: {e}", "ERROR")
  477. def perform_click2(self, emu_index, window_title, content):
  478. """执行点击操作"""
  479. x, y = 508, 252
  480. self.log_message(f"开始在模拟器 {emu_index} 上点击位置 ({x}, {y})")
  481. try:
  482. manager = MuMuEmulatorManager(self.mumu_manager_path)
  483. # 先获取adb端口
  484. adb_port = manager.get_adb_port(emu_index, self.log_message)
  485. if not adb_port:
  486. self.log_message(f"❌ 无法获取模拟器 {emu_index} 的ADB端口", "ERROR")
  487. return
  488. # 执行点击
  489. if manager.tap(emu_index, x, y, self.log_message):
  490. self.log_message(f"✅ 点击成功!模拟器 {emu_index} 位置 ({x}, {y})")
  491. rectX, rectY = activate_window_and_get_position(window_title)
  492. time.sleep(2) # 短暂等待窗口激活
  493. click_screen(rectX + 339, rectY + 576)
  494. time.sleep(1)
  495. showImageBox = show_image_at_position("C:\\Users\\mail\\Downloads\\chepai\\" + content["tableData"][2] + ".png", rectX + 273, rectY + 549 )
  496. # 开始检测是否扫描
  497. color1 = get_emulator_pixel_color(self.mumu_manager_path, emu_index, 530, 1200)
  498. while color1 != "#007AFF": # 假设白色表示未扫描
  499. self.log_message(f"当前颜色: {color1}, 等待扫描完成...")
  500. time.sleep(1)
  501. color1 = get_emulator_pixel_color(self.mumu_manager_path, emu_index, 530, 1200)
  502. # 关闭窗口
  503. showImageBox.destroy()
  504. self.log_message(f"关闭二维码窗口!")
  505. manager.tap(emu_index, 323, 718, self.log_message)
  506. time.sleep(2)
  507. manager.tap(emu_index, 652, 748, self.log_message)
  508. time.sleep(1)
  509. manager.tap(emu_index, 347, 918, self.log_message)
  510. time.sleep(1)
  511. input_text_to_emulator(self.mumu_manager_path, emu_index, random.randint(35, 36))
  512. time.sleep(1)
  513. time.sleep(1)
  514. manager.tap(emu_index, 530, 1200, self.log_message)
  515. time.sleep(1)
  516. manager.tap(emu_index, 419, 765, self.log_message)
  517. else:
  518. self.log_message(f"❌ 点击失败", "ERROR")
  519. except Exception as e:
  520. self.log_message(f"❌ 执行出错: {e}", "ERROR")
  521. def main():
  522. root = tk.Tk()
  523. app = SimpleMuMuManager(root)
  524. root.mainloop()
  525. if __name__ == "__main__":
  526. main()