# -*- coding: utf-8 -*- """首次激活:必须填写中控地址 + 激活码,不允许离线运行。""" from __future__ import annotations import tkinter as tk from tkinter import messagebox, ttk from typing import Optional import hub_client from device_store import is_activated, load_device, machine_fingerprint def _bring_front(win: tk.Misc) -> None: try: win.update_idletasks() win.deiconify() win.lift() win.focus_force() win.attributes("-topmost", True) win.after(250, lambda: win.attributes("-topmost", False)) except Exception: pass def ensure_activated(parent: Optional[tk.Misc] = None) -> bool: """ - 已激活:探测中控,成功则放行;失败则提示重试/退出(不允许离线)。 - 未激活:必须激活成功才能进入。 """ if is_activated(): if hub_client.ping(): return True return _ask_retry_or_exit(parent) return _show_activation_form(parent) def _ask_retry_or_exit(parent: Optional[tk.Misc]) -> bool: owns = parent is None root = parent or tk.Tk() if owns: root.withdraw() try: while True: _bring_front(root) retry = messagebox.askretrycancel( "无法连接中控", "客户端不允许离线运行。\n请确认中控已启动且本机网络正常后重试。\n\n点「重试」再次连接,点「取消」退出。", parent=root, ) if not retry: return False if hub_client.ping(): return True finally: if owns: try: root.destroy() except Exception: pass def _show_activation_form(parent: Optional[tk.Misc]) -> bool: owns_root = parent is None root = parent or tk.Tk() try: win = root if owns_root else tk.Toplevel(root) win.title("首次激活 · 黄金辅助") win.minsize(520, 400) win.geometry("520x400") win.resizable(True, True) result = {"ok": False} device = load_device() btn_bar = ttk.Frame(win, padding=(16, 10, 16, 16)) btn_bar.pack(side=tk.BOTTOM, fill=tk.X) body = ttk.Frame(win, padding=16) body.pack(side=tk.TOP, fill=tk.BOTH, expand=True) ttk.Label( body, text="必须激活后才能使用。填写中控地址与激活码,成功后本机保存,以后自动连接。", wraplength=470, ).pack(anchor="w") ttk.Label(body, text="中控地址(例:http://192.168.1.10:5800)").pack( anchor="w", pady=(14, 4) ) var_server = tk.StringVar(value=device.get("server") or "http://127.0.0.1:5800") ttk.Entry(body, textvariable=var_server).pack(fill=tk.X, ipady=3) ttk.Label(body, text="激活码(网页下载中心生成)").pack(anchor="w", pady=(12, 4)) var_code = tk.StringVar() ttk.Entry(body, textvariable=var_code).pack(fill=tk.X, ipady=3) ttk.Label(body, text="本机名称(可改)").pack(anchor="w", pady=(12, 4)) var_name = tk.StringVar(value=device.get("machine_name") or "") ttk.Entry(body, textvariable=var_name).pack(fill=tk.X, ipady=3) status = ttk.Label(body, text="", foreground="#888") status.pack(anchor="w", pady=(14, 0)) def do_exit(): result["ok"] = False win.destroy() def do_ok(): server = var_server.get().strip().rstrip("/") code = var_code.get().strip() if not server or not code: status.configure(text="请填写中控地址与激活码", foreground="#f6465d") return status.configure(text="正在激活…", foreground="#888") win.update_idletasks() try: hub_client.activate( server, code, machine_fingerprint(), var_name.get().strip() or "PC" ) result["ok"] = True messagebox.showinfo( "激活成功", f"已绑定中控:{server}\n以后打开将自动连接。", parent=win, ) win.destroy() except hub_client.HubError as exc: status.configure(text=str(exc), foreground="#f6465d") ttk.Button(btn_bar, text="退出", command=do_exit).pack(side=tk.LEFT, ipadx=8, ipady=4) ttk.Button(btn_bar, text="确认激活", command=do_ok).pack(side=tk.RIGHT, ipadx=12, ipady=4) win.bind("", lambda _e: do_ok()) win.protocol("WM_DELETE_WINDOW", do_exit) _bring_front(win) try: win.grab_set() except Exception: pass win.wait_window() return result["ok"] finally: if owns_root: try: if root.winfo_exists(): root.destroy() except Exception: pass