# -*- 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: """ - 已激活(本地有 server + token):直接放行,不再弹窗;中控地址固定复用。 - 未激活:弹出首次激活窗,成功后写入 device.json。 """ if is_activated(): # 后台轻量探测(失败也不打扰,主界面仍可用,上报会静默失败) try: hub_client.ping() except Exception: pass return True owns_root = False if parent is not None: root = parent else: root = tk.Tk() owns_root = True try: if owns_root: win = root else: win = tk.Toplevel(root) win.title("首次激活 · 黄金辅助") win.minsize(520, 420) win.geometry("520x420") 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_skip(): # 离线:不写 token,下次仍会提示首次激活 result["ok"] = True 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_skip).pack( side=tk.LEFT, ipadx=6, 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_skip) _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