# -*- 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 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: """已激活且能 ping 通则通过;否则弹出激活窗。返回是否可继续。""" device = load_device() owns_root = False if parent is not None: root = parent else: root = tk.Tk() owns_root = True try: if device.get("token") and device.get("server"): if hub_client.ping(): return True _bring_front(root) if not messagebox.askyesno( "激活校验", "无法连接中控或令牌失效,是否重新激活?\n选「否」将以离线模式继续(不上报复盘)。", parent=root, ): return True # 单独可见窗口,避免「正在启动」残窗 + 按钮被裁切 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} # 底部按钮区先占位,保证高 DPI 下仍可见 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(): result["ok"] = True win.destroy() def do_ok(): server = var_server.get().strip() 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( "激活成功", "已绑定账户与机器,成交将上报复盘中心。", 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=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_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