Browse Source

feat(gui): 添加自动登录和倒计时运行功能

- 在 GUI 初始化时自动尝试登录并设置会话密钥
- 添加倒计时标签显示下次检测时间
- 支持通过 protector runner 触发定期运行任务
- 实现每秒更新倒计时并在归零时执行保护逻辑
- 提供获取扫描间隔的方法以支持动态配置
- 记录上次运行时间以便外部协调避免重复运行
- 优化 GUI 启动流程,传递 protector runner 实例
mcbaiyun 2 tháng trước cách đây
mục cha
commit
a92c578c72
3 tập tin đã thay đổi với 88 bổ sung5 xóa
  1. 70 3
      gui.py
  2. 2 2
      main.py
  3. 16 0
      protector.py

+ 70 - 3
gui.py

@@ -30,7 +30,7 @@ def save_cfg(cfg: dict):
 
 
 class ProtectorGUI(tk.Tk):
-    def __init__(self):
+    def __init__(self, protector_runner=None):
         super().__init__()
         self.title("Protector GUI")
         self.geometry("700x500")
@@ -90,6 +90,38 @@ class ProtectorGUI(tk.Tk):
 
         self.load_values()
 
+        # 自动在后台尝试登录(启动后立即)
+        def _auto_login():
+            try:
+                resp, sess_cookie = login()
+                if sess_cookie:
+                    set_sess_key(sess_cookie)
+                    # 不弹出大量通知,只有在需要时可打开下面这一行
+                    # messagebox.showinfo("登录", f"自动登录完成, 状态: {resp.status_code}")
+            except Exception as e:
+                # 登录失败不阻塞 GUI,记录到控制台/弹出一条错误提示
+                try:
+                    messagebox.showerror("自动登录失败", str(e))
+                except Exception:
+                    print("自动登录失败:", e)
+
+        threading.Thread(target=_auto_login, daemon=True).start()
+
+        # Protector runner instance (optional) for countdown and triggering runs
+        self.protector_runner = protector_runner
+        # countdown label
+        self.countdown_var = tk.StringVar(value="Protector: idle")
+        self.countdown_label = tk.Label(self, textvariable=self.countdown_var)
+        self.countdown_label.pack(anchor="ne", padx=8, pady=4)
+
+        # start initial delayed run countdown (10 seconds) if runner provided
+        if self.protector_runner is not None:
+            self._initial_delay = 10
+            self._countdown_seconds = self._initial_delay
+            # schedule countdown update every 1 second via tkinter's after
+            self.after(1000, self._update_countdown)
+
+
     def load_values(self):
         self.cfg = load_cfg()
         self.base_entry.delete(0, tk.END)
@@ -209,8 +241,43 @@ class ProtectorGUI(tk.Tk):
             messagebox.showerror("错误", "删除失败")
 
 
-def run_gui():
-    app = ProtectorGUI()
+    def _update_countdown(self):
+        """Update countdown label every second and trigger protector run when it reaches zero."""
+        try:
+            if not self.protector_runner:
+                return
+            # Update label
+            try:
+                self.countdown_var.set(f"下一次检测:{self._countdown_seconds}s")
+            except Exception:
+                self.countdown_var.set("Protector: running")
+
+            if self._countdown_seconds <= 0:
+                # trigger a run in background
+                try:
+                    threading.Thread(target=self.protector_runner.run_once, daemon=True).start()
+                except Exception as e:
+                    print("触发 protector 运行失败:", e)
+                # reset countdown to configured interval
+                try:
+                    self._countdown_seconds = int(self.protector_runner.get_interval())
+                except Exception:
+                    self._countdown_seconds = self._initial_delay
+            else:
+                self._countdown_seconds -= 1
+
+        except Exception as e:
+            # keep ticking even on error
+            print("倒计时更新出错:", e)
+
+        # schedule next tick
+        try:
+            self.after(1000, self._update_countdown)
+        except Exception:
+            pass
+
+def run_gui(protector_runner=None):
+    app = ProtectorGUI(protector_runner=protector_runner)
     app.mainloop()
 
 

+ 2 - 2
main.py

@@ -20,8 +20,8 @@ def main():
 		# start background protector
 		pr = ProtectorRunner()
 		pr.start()
-		# launch GUI (blocking)
-		gui.run_gui()
+		# launch GUI (blocking) and pass protector runner so GUI can display countdown
+		gui.run_gui(protector_runner=pr)
 		# when GUI exits, stop protector
 		pr.stop()
 		return

+ 16 - 0
protector.py

@@ -20,8 +20,15 @@ class ProtectorRunner:
         cfg = load_config()
         self.interval = int(cfg.get("scan_interval", 60))
         self._stop = threading.Event()
+        self.last_run_time: Optional[float] = None
 
     def run_once(self):
+        # record start time to help external coordinators avoid duplicate runs
+        try:
+            self.last_run_time = time.time()
+        except Exception:
+            pass
+
         items = protector_list.load_list()
         for entry in items:
             target = entry.get("target_ip")
@@ -83,6 +90,15 @@ class ProtectorRunner:
         self._stop.set()
 
 
+    def get_interval(self) -> int:
+        """Return current scan interval in seconds."""
+        try:
+            cfg = load_config()
+            return int(cfg.get("scan_interval", self.interval))
+        except Exception:
+            return self.interval
+
+
 def run_protector_blocking_once():
     pr = ProtectorRunner()
     pr.run_once()