# ===================== 【根号七的工具箱】 =====================

import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext, colorchooser, filedialog
from PIL import ImageTk, Image, ImageDraw
import sys
import os
import webbrowser
import time
import pyautogui
from pynput import keyboard
import datetime
import re
import threading
import requests
import geocoder
import hashlib
import pyttsx3

# 全局打印计数器
print_counter = 1


# 带编号的打印函数
def numbered_print(msg):
    global print_counter
    print(f"({print_counter}) {msg}")
    print_counter += 1


# 实时时间
def get_time_str():
    t = datetime.datetime.now()
    return f"{t.hour:02d}:{t.minute:02d}:{t.second:02d}"


# 版本、版本号修改
VERSION = " " + "内测版"
VERNO = " " + "v2.3.0"


class ToolboxApp:
    def __init__(self, root):
        # 程序主界面与功能初始化
        self.root = root
        self.root.title(f"根号七的工具箱{VERSION}{VERNO}")
        self.root.geometry("1280x800")
        self.root.minsize(1000, 650)

        # 主题配色配置
        self.bg_color = "#F0F0F0"
        self.primary_color = "#1F7A48"
        self.second_color = "#E3F2EB"  # 侧边栏选中背景色
        self.hover_color = "#D4E8DC"  # 侧边栏鼠标悬停颜色
        self.text_color = "#333333"
        self.button_bg = "#1F7A48"  # 普通按钮背景色（跟随主题）
        self.is_dark_mode = False
        self.root.configure(bg=self.bg_color)

        # 侧边栏动画参数
        self.nav_anim_id = None
        self.nav_collapse_width = 60
        self.nav_expand_width = 240

        # 用户信息
        self.username = "默认用户"
        self.is_editing = False
        self.user_avatar = self.load_circle_avatar("头像.png", size=32)
        self.zan_img = None
        self.qun_img = None

        # 设置相关变量
        self.settings_icon = None
        self.shortcuts = {
            "clicker_toggle": "F9",
            "float_toggle": "F10",
            "fullscreen": "F11",
            "quit": "Ctrl+Q"
        }
        self.theme_color = self.primary_color

        # 连点器功能变量
        self.clicker_running = False
        self.clicker_thread = None
        self.hotkey_enabled = tk.BooleanVar(value=False)

        # 悬浮字幕功能变量
        self.float_running = False
        self.float_hotkey_enabled = tk.BooleanVar(value=False)
        self.float_listener = None
        self.float_window = None
        self.float_label = None
        self.float_x = 100
        self.float_y = 100
        self.float_font_size = 24
        self.float_color = "#ff0000"
        self.float_bg_color = "#00FF00"
        self.float_alpha = tk.DoubleVar(value=100)
        self.float_refresh_id = None
        self.float_font_family = "微软雅黑"

        # 番茄钟变量
        self.pomodoro_running = False
        self.pomodoro_minutes = 25
        self.pomodoro_seconds = 0
        self.pomodoro_remaining = 25 * 60
        self.pomodoro_type = "work"
        self.pomodoro_thread = None

        # 功能模块公共变量
        self.current_module = None
        self.calc_expression = ""
        self.calc_history = []
        self.current_nav_btn = None

        # 存储所有页面Frame的字典
        self.pages = {}

        # 界面与快捷键初始化
        self.setup_window_icon()
        self.setup_global_style()
        self.setup_layout()
        self.bind_shortcuts()
        self.setup_clicker_global_hotkeys()
        self.setup_float_global_hotkeys()

        # 预加载所有页面
        self.preload_all_pages()

        # 显示首页
        self.show_page("home")

    # 悬浮字幕核心功能
    def parse_float_text(self, raw_text):
        now = datetime.datetime.now()
        var_map = {
            "{year}": str(now.year),
            "{month}": f"{now.month:02d}",
            "{day}": f"{now.day:02d}",
            "{hour}": f"{now.hour:02d}",
            "{minute}": f"{now.minute:02d}",
            "{second}": f"{now.second:02d}"
        }
        text = raw_text
        for k, v in var_map.items():
            text = text.replace(k, v)

        math_pat = re.compile(r"\{math:(.+?)\}")

        def calc_match(m):
            expr = m.group(1)
            try:
                res = eval(expr, {"__builtins__": None}, {})
                return str(res)
            except:
                return "错误"

        text = math_pat.sub(calc_match, text)
        text = text.replace("\\n", "\n")
        return text

    def float_auto_refresh(self):
        if self.float_window and self.float_label and hasattr(self, 'float_text_entry'):
            try:
                if not self.float_text_entry.winfo_exists():
                    return
                raw = self.float_text_entry.get("1.0", tk.END).strip()
                real_txt = self.parse_float_text(raw)
                self.float_label.config(text=real_txt)
            except:
                return
        self.float_refresh_id = self.root.after(1000, self.float_auto_refresh)

    def setup_float_global_hotkeys(self):
        def on_f10_press(key):
            try:
                target_key = getattr(keyboard.Key, self.shortcuts["float_toggle"].lower(), None)
                if target_key and key == target_key and self.float_hotkey_enabled.get():
                    self.root.after(0, self.toggle_float)
            except:
                pass

        self.float_listener = keyboard.Listener(on_press=on_f10_press)
        self.float_listener.daemon = True
        self.float_listener.start()

    def toggle_float(self):
        if not self.float_running:
            self.show_float_text()
        else:
            self.hide_float_text()

    # 连点器核心功能
    def setup_clicker_global_hotkeys(self):
        self.hotkey_listener = None

        def on_press(key):
            if not self.hotkey_enabled.get():
                return
            try:
                target_key = getattr(keyboard.Key, self.shortcuts["clicker_toggle"].lower(), None)
                if target_key and key == target_key:
                    self.root.after(0, self.toggle_clicker)
            except:
                pass

        try:
            self.hotkey_listener = keyboard.Listener(on_press=on_press, daemon=True)
            self.hotkey_listener.start()
        except:
            pass

    def toggle_clicker(self):
        if self.clicker_running:
            self.stop_clicker()
        else:
            self.start_clicker()

    def start_clicker(self):
        if self.clicker_running:
            return
        try:
            interval = float(self.click_interval.get()) / 1000
            count = int(self.click_times.get())
            btn_text = self.click_btn.get()
            mode = self.click_mode.get()
            btn = "left" if btn_text == "左键" else "right"
        except:
            messagebox.showwarning("提示", "请输入有效数字")
            return

        self.clicker_running = True
        self.click_status.config(text="状态：运行中", fg="#e53e3e")

        def task():
            n = 0
            while self.clicker_running:
                pyautogui.click(button=btn) if mode == "单击" else pyautogui.doubleClick(button=btn)
                n += 1
                if count != -1 and n >= count:
                    break
                time.sleep(interval)
            self.clicker_running = False
            self.root.after(0, lambda: self.click_status.config(text="状态：已停止", fg=self.text_color))

        self.clicker_thread = threading.Thread(target=task, daemon=True)
        self.clicker_thread.start()

    def stop_clicker(self):
        self.clicker_running = False
        self.click_status.config(text="状态：已停止", fg=self.text_color)

    # 头像加载功能
    def load_circle_avatar(self, img_path, size=32):
        try:
            img = Image.open(img_path).convert("RGBA")
            img = img.resize((size, size), Image.LANCZOS)
            mask = Image.new("L", (size, size), 0)
            draw = ImageDraw.Draw(mask)
            draw.ellipse((0, 0, size, size), fill=255)
            circle_img = Image.new("RGBA", (size, size), (255, 255, 255, 0))
            circle_img.paste(img, (0, 0), mask=mask)
            numbered_print(f"[{get_time_str()}] 图片 \"头像.png\" 加载成功")
            return ImageTk.PhotoImage(circle_img)
        except Exception:
            numbered_print(f"[{get_time_str()}] 图片 \"头像.png\" 加载失败，未找到图片")
            return self.create_default_avatar(size)

    def create_default_avatar(self, size=32):
        img = Image.new("RGBA", (size, size), (0, 0, 0, 0))
        draw = ImageDraw.Draw(img)
        draw.ellipse((0, 0, size, size), fill="#CCCCCC")
        draw.ellipse((size * 0.25, size * 0.15, size * 0.75, size * 0.45), fill="#AAAAAA")
        draw.rectangle((size * 0.2, size * 0.5, size * 0.8, size * 0.9), fill="#AAAAAA")
        return ImageTk.PhotoImage(img)

    def setup_window_icon(self):
        try:
            icon_path = "图标4.ico"
            numbered_print(f"[{get_time_str()}] 图标 \"{icon_path}\" 加载成功")
            if os.path.exists(icon_path):
                self.root.iconbitmap(icon_path)
        except Exception:
            pass

    # ===================== 界面样式与布局 =====================
    def setup_global_style(self):
        self.style = ttk.Style()
        self.style.theme_use("clam")
        self.style.configure("Primary.TButton", font=("微软雅黑", 10, "bold"), background=self.button_bg,
                             foreground="white", padding=12)
        self.style.map("Primary.TButton", background=[('active', self.darken_color(self.button_bg))])
        self.style.configure("Nav.TButton", font=("微软雅黑", 11), background="white", foreground=self.text_color,
                             padding=12, borderwidth=0)
        # 鼠标悬停使用 hover_color，跟随深色/浅色模式
        self.style.map("Nav.TButton", background=[('active', self.hover_color), ('pressed', self.hover_color)])
        # 选中的侧边栏按钮背景跟随 second_color（主题色）
        self.style.configure("Selected.Nav.TButton", font=("微软雅黑", 11, "bold"), background=self.second_color,
                             foreground=self.text_color, padding=12, borderwidth=0, relief=tk.FLAT)
        self.style.map("Selected.Nav.TButton", background=[('active', self.darken_color(self.second_color, 0.8))])

    def darken_color(self, color, factor=0.7):
        color = color.lstrip('#')
        r = int(int(color[0:2], 16) * factor)
        g = int(int(color[2:4], 16) * factor)
        b = int(int(color[4:6], 16) * factor)
        return f"#{r:02x}{g:02x}{b:02x}"

    # ===================== 渐变功能 =====================
    def fade_color(self, from_color, to_color, steps=8, delay=15):
        """颜色渐变过渡"""

        def hex_to_rgb(hex_color):
            hex_color = hex_color.lstrip('#')
            return tuple(int(hex_color[i:i + 2], 16) for i in (0, 2, 4))

        def rgb_to_hex(rgb):
            return f"#{rgb[0]:02x}{rgb[1]:02x}{rgb[2]:02x}"

        r1, g1, b1 = hex_to_rgb(from_color)
        r2, g2, b2 = hex_to_rgb(to_color)

        def update_step(step):
            if step > steps:
                return
            r = r1 + (r2 - r1) * step // steps
            g = g1 + (g2 - g1) * step // steps
            b = b1 + (b2 - b1) * step // steps
            color = rgb_to_hex((r, g, b))

            # 应用渐变颜色
            self.primary_color = color
            self.button_bg = color
            self.style.configure("Primary.TButton", background=color)
            self.style.map("Primary.TButton", background=[('active', self.darken_color(color))])
            self.header_frame.configure(bg=color)
            self.header_icon.configure(bg=color)
            self.header_title.configure(bg=color)
            self.settings_btn.configure(bg=color)

            self.root.after(delay, lambda: update_step(step + 1))

        update_step(1)

    def fade_bg(self, from_color, to_color, steps=10, delay=15):
        """背景颜色渐变过渡"""

        def hex_to_rgb(hex_color):
            hex_color = hex_color.lstrip('#')
            return tuple(int(hex_color[i:i + 2], 16) for i in (0, 2, 4))

        def rgb_to_hex(rgb):
            return f"#{rgb[0]:02x}{rgb[1]:02x}{rgb[2]:02x}"

        r1, g1, b1 = hex_to_rgb(from_color)
        r2, g2, b2 = hex_to_rgb(to_color)

        def update_step(step):
            if step > steps:
                return
            r = r1 + (r2 - r1) * step // steps
            g = g1 + (g2 - g1) * step // steps
            b = b1 + (b2 - b1) * step // steps
            color = rgb_to_hex((r, g, b))

            # 应用渐变背景
            self.bg_color = color
            self.root.configure(bg=color)
            self.main_container.configure(bg=color)
            self.main_frame.configure(bg=color)

            self.root.after(delay, lambda: update_step(step + 1))

        update_step(1)

    def clear_main_frame(self):
        # 不再销毁widget，只是隐藏所有页面
        pass

    def show_page(self, page_name):
        """显示指定的页面"""
        # 隐藏所有页面
        for name, page in self.pages.items():
            page.place_forget()

        # 显示选中的页面
        if page_name in self.pages:
            self.pages[page_name].place(x=0, y=0, relwidth=1, relheight=1)
            self.current_module = page_name

    def bind_shortcuts(self):
        self.root.bind("<F11>", self.toggle_fullscreen)
        self.root.bind("<Escape>", self.exit_fullscreen)
        self.root.bind("<Control-q>", self.quit_app)

    def toggle_fullscreen(self, event=None):
        is_full = self.root.attributes("-fullscreen")
        self.root.attributes("-fullscreen", not is_full)

    def exit_fullscreen(self, event=None):
        self.root.attributes("-fullscreen", False)

    def quit_app(self, event=None):
        if messagebox.askokcancel("退出确认", "确定要退出工具箱吗？"):
            self.root.destroy()
            sys.exit(0)

    # ===================== 侧边栏动画 =====================
    def animate_expand(self):
        if self.nav_anim_id is not None:
            self.root.after_cancel(self.nav_anim_id)

        cur = self.nav_frame.winfo_width()
        tar = self.nav_expand_width
        if cur >= tar:
            self.nav_frame.config(width=tar)
            self.nav_anim_id = None
            return

        diff = tar - cur
        step = max(1.5, diff / 8)
        self.nav_frame.config(width=cur + step)
        self.nav_anim_id = self.root.after(15, self.animate_expand)

    def animate_collapse(self):
        if self.nav_anim_id is not None:
            self.root.after_cancel(self.nav_anim_id)

        cur = self.nav_frame.winfo_width()
        tar = self.nav_collapse_width
        if cur <= tar:
            self.nav_frame.config(width=tar)
            self.nav_anim_id = None
            return

        diff = cur - tar
        step = max(1.5, diff / 8)
        self.nav_frame.config(width=cur - step)
        self.nav_anim_id = self.root.after(15, self.animate_collapse)

    def set_selected_nav(self, selected_btn, page_name):
        for btn, _, _, pname in self.nav_buttons:
            btn.config(style="Nav.TButton")
        selected_btn.config(style="Selected.Nav.TButton")
        self.current_nav_btn = selected_btn
        self.show_page(page_name)

    def setup_layout(self):
        # 顶部标题栏
        self.header_frame = tk.Frame(self.root, bg=self.primary_color, height=60)
        self.header_frame.pack(fill=tk.X, side=tk.TOP)
        self.header_frame.pack_propagate(False)

        self.header_icon = tk.Label(self.header_frame, text="🌵", font=("微软雅黑", 20, "bold"),
                                    bg=self.primary_color, fg="white")
        self.header_icon.pack(side=tk.LEFT, padx=(20, 5), pady=12)
        self.header_title = tk.Label(self.header_frame, text="根号七的工具箱", font=("微软雅黑", 18, "bold"),
                                     bg=self.primary_color, fg="white")
        self.header_title.pack(side=tk.LEFT, pady=12)

        # 右上角设置按钮
        self.settings_btn = tk.Button(
            self.header_frame,
            text="⚙️",
            font=("微软雅黑", 16),
            bg=self.primary_color,
            fg="white",
            relief=tk.FLAT,
            cursor="hand2",
            command=lambda: self.show_page("settings")
        )
        self.settings_btn.pack(side=tk.RIGHT, padx=20)

        # 主内容区容器
        self.main_container = tk.Frame(self.root, bg=self.bg_color)
        self.main_container.pack(fill=tk.BOTH, expand=True, side=tk.LEFT, padx=(self.nav_collapse_width, 0))

        # 主内容区 - 作为页面放置的容器（注意：这里改为了 main_container 而不是 right_container）
        self.main_frame = tk.Frame(self.main_container, bg=self.bg_color)
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

        # 左侧导航栏
        self.nav_frame = tk.Frame(self.root, bg="white")
        self.nav_frame.place(x=0, y=60, relheight=1, height=-60)
        self.nav_frame.pack_propagate(False)
        self.nav_frame.config(width=self.nav_collapse_width)

        def check_mouse_pos():
            try:
                mx, my = self.root.winfo_pointerxy()
                nx1 = self.nav_frame.winfo_rootx()
                nx2 = nx1 + self.nav_frame.winfo_width()
                ny1 = self.nav_frame.winfo_rooty()
                ny2 = ny1 + self.nav_frame.winfo_height()

                if self.nav_anim_id is not None:
                    self.root.after_cancel(self.nav_anim_id)
                    self.nav_anim_id = None

                if nx1 <= mx <= nx2 and ny1 <= my <= ny2:
                    self.animate_expand()
                else:
                    self.animate_collapse()
            except:
                pass
            self.root.after(30, check_mouse_pos)

        check_mouse_pos()

        self.nav_buttons = []
        nav_config = [
            ("🏠", "🏠 首页", "home"),
            ("🧭", "🧭 网址导航", "nav"),
            ("🧮", "🧮 计算器", "calculator"),
            ("🖱", "🖱 鼠标指针辅助器", "clicker"),
            ("📝", "📝 自定义漂浮字幕", "float_text"),
            ("🌤", "🌤 天气预报", "weather"),
            ("📅", "📅 签到中心", "sign_fortune"),
            ("🔐", "🔐 文件哈希校验", "hash"),
            ("🍅", "🍅 番茄钟", "pomodoro"),
            ("📱", "📱 二维码生成器", "qrcode"),
            ("🌐", "🌐 多语言翻译", "translate"),
            ("💖", "💖 支持根号七", "support")
        ]
        for icon, text, page_name in nav_config:
            btn = ttk.Button(self.nav_frame, text=icon, style="Nav.TButton")
            btn.config(command=lambda b=btn, pn=page_name: self.set_selected_nav(b, pn))
            btn.pack(fill=tk.X, pady=4, padx=8)
            self.nav_buttons.append((btn, icon, text, page_name))

        bottom_frame = tk.Frame(self.nav_frame, bg="white")
        bottom_frame.pack(side=tk.BOTTOM, fill=tk.X, padx=0, pady=0)
        self.user_info_label = tk.Label(bottom_frame, text="——用户信息——————————", font=("微软雅黑", 10, "bold"),
                                        bg="white", fg="#666666")
        self.user_info_label.pack(anchor=tk.W, padx=12, pady=(0, 2))

        self.tip_label = None

        user_row = tk.Frame(bottom_frame, bg="white")
        user_row.pack(anchor=tk.W, padx=8, pady=(0, 10))
        self.user_avatar_label = tk.Label(user_row, image=self.user_avatar, bg="white")
        self.user_avatar_label.pack(side=tk.LEFT, padx=4)
        self.name_label = tk.Label(user_row, text=self.username, font=("微软雅黑", 11), bg="white", cursor="hand2",
                                   fg=self.text_color)
        self.name_label.pack(side=tk.LEFT)
        self.name_label.bind("<Button-1>", lambda e: self.start_edit_name())

        self.name_edit_var = tk.StringVar(value=self.username)
        self.name_entry = None
        self.confirm_btn = None
        self.cancel_btn = None

        def update_btn_text():
            w = self.nav_frame.winfo_width()
            for btn, ico, txt, _ in self.nav_buttons:
                btn.config(text=txt if w > 180 else ico)
            self.root.after(50, update_btn_text)

        update_btn_text()

        # 注意：这里不能调用 set_selected_nav，因为页面还没有预加载
        # 先选中第一个按钮的样式，等页面预加载完成后在 __init__ 中调用 show_page
        first_btn = self.nav_buttons[0][0]
        for btn, _, _, _ in self.nav_buttons:
            btn.config(style="Nav.TButton")
        first_btn.config(style="Selected.Nav.TButton")
        self.current_nav_btn = first_btn

        self.footer_frame = tk.Frame(self.root, bg="#DCDCDC", height=28)
        self.footer_frame.pack(fill=tk.X, side=tk.BOTTOM, before=self.header_frame)
        self.footer_frame.pack_propagate(False)

        self.version_label = tk.Label(self.footer_frame,
                                      text=f"根号七的工具箱{VERSION} | 版本号:{VERNO}",
                                      font=("微软雅黑", 9),
                                      bg="#DCDCDC",
                                      fg="black")
        self.version_label.pack(side=tk.RIGHT, padx=15, pady=4)

        self.nav_frame.lift()

    # 昵称修改功能
    def start_edit_name(self):
        if self.is_editing:
            return
        self.is_editing = True
        self.name_label.pack_forget()

        self.name_edit_var.set(self.username)
        self.name_entry = tk.Entry(self.name_label.master, textvariable=self.name_edit_var,
                                   font=("微软雅黑", 11), width=8, bg="#f8f8f8")
        self.name_entry.pack(side=tk.LEFT, padx=(2, 4))
        self.name_entry.focus()

        self.confirm_btn = tk.Button(self.name_label.master, text="确定", font=("微软雅黑", 9),
                                     bg="#3a7aff", fg="white", relief=tk.FLAT, padx=6, pady=1,
                                     command=self.confirm_edit_name)
        self.cancel_btn = tk.Button(self.name_label.master, text="取消", font=("微软雅黑", 9),
                                    bg="white", fg="#333", relief=tk.FLAT, padx=6, pady=1,
                                    command=self.cancel_edit_name)
        self.confirm_btn.pack(side=tk.LEFT, padx=2)
        self.cancel_btn.pack(side=tk.LEFT, padx=2)

        self.name_entry.bind("<Return>", lambda e: self.confirm_edit_name())
        self.name_entry.bind("<Escape>", lambda e: self.cancel_edit_name())

    def cancel_edit_name(self):
        self.hide_tip()
        self.is_editing = False
        self.name_entry.destroy()
        self.confirm_btn.destroy()
        self.cancel_btn.destroy()
        self.name_label.pack(side=tk.LEFT)

    def confirm_edit_name(self):
        new_name = self.name_edit_var.get().strip()
        if len(new_name) == 0 or len(new_name) > 8:
            self.show_tip("长度必须 1~8 位")
            return
        if not re.fullmatch(r'^[\u4e00-\u9fa5a-zA-Z0-9\.\-_]+$', new_name):
            self.show_tip("仅支持中文、英文、小数点、划线 和 下划线")
            return

        self.hide_tip()
        self.username = new_name
        self.name_label.config(text=new_name)
        self.cancel_edit_name()

    def show_tip(self, msg):
        self.hide_tip()
        self.tip_label = tk.Label(self.nav_frame, text=msg, font=("微软雅黑", 9),
                                  bg="#ffebee", fg="#d32f2f", padx=6, pady=2)
        self.tip_label.place(relx=0.05, rely=0.82)

    def hide_tip(self):
        if self.tip_label:
            self.tip_label.destroy()
            self.tip_label = None

    def preload_all_pages(self):
        """预加载所有页面"""
        # 首页
        self.pages["home"] = self.preload_page_home(self.main_frame)
        # 网址导航
        self.pages["nav"] = self.preload_page_nav(self.main_frame)
        # 计算器
        self.pages["calculator"] = self.preload_page_calculator(self.main_frame)
        # 连点器
        self.pages["clicker"] = self.preload_page_clicker(self.main_frame)
        # 漂浮字幕
        self.pages["float_text"] = self.preload_page_float_text(self.main_frame)
        # 天气预报
        self.pages["weather"] = self.preload_page_weather(self.main_frame)
        # 签到中心
        self.pages["sign_fortune"] = self.preload_page_sign_fortune(self.main_frame)
        # 文件哈希校验
        self.pages["hash"] = self.preload_page_hash(self.main_frame)
        # 番茄钟
        self.pages["pomodoro"] = self.preload_page_pomodoro(self.main_frame)
        # 二维码生成器
        self.pages["qrcode"] = self.preload_page_qrcode(self.main_frame)
        # 多语言翻译
        self.pages["translate"] = self.preload_page_translate(self.main_frame)
        # 支持根号七
        self.pages["support"] = self.preload_page_support(self.main_frame)
        # 设置页面
        self.pages["settings"] = self.preload_page_settings(self.main_frame)

    def preload_page_home(self, parent):
        """预加载首页"""
        frame = tk.Frame(parent, bg=self.bg_color)

        # 创建带滚动条的容器
        main_container = tk.Frame(frame, bg=self.bg_color)
        main_container.pack(fill=tk.BOTH, expand=True)

        canvas = tk.Canvas(main_container, bg=self.bg_color, highlightthickness=0)
        scrollbar = tk.Scrollbar(main_container, orient=tk.VERTICAL, command=canvas.yview)
        content_frame = tk.Frame(canvas, bg=self.bg_color)

        canvas.configure(yscrollcommand=scrollbar.set)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        def update_scrollregion(event):
            canvas.config(scrollregion=canvas.bbox("all"))

        content_frame.bind("<Configure>", update_scrollregion)

        def update_content_width(event):
            try:
                canvas.itemconfig(win_id, width=canvas.winfo_width())
            except:
                pass

        canvas.bind("<Configure>", update_content_width)

        win_id = canvas.create_window((0, 0), window=content_frame, anchor="nw")

        def on_mousewheel(event):
            canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")

        canvas.bind("<MouseWheel>", on_mousewheel)

        tk.Label(content_frame, text="欢迎使用 根号七的工具箱",
                 font=("微软雅黑", 24, "bold"), bg=self.bg_color,
                 fg=self.primary_color).pack(pady=40)

        tk.Label(content_frame, text="左侧工具栏可选择对应工具",
                 font=("微软雅黑", 14), bg=self.bg_color,
                 fg=self.text_color).pack(pady=10)

        tk.Label(content_frame, text="F11切换全屏 | Esc退出全屏 | Ctrl+Q退出程序",
                 font=("微软雅黑", 12), bg=self.bg_color,
                 fg=self.text_color).pack(pady=20)

        notice_frame = tk.Frame(content_frame, bg="white" if not self.is_dark_mode else "#2d2d2d", bd=2,
                                relief=tk.RIDGE)
        notice_frame.pack(fill=tk.X, padx=20, pady=20, expand=True)

        frame_bg = "white" if not self.is_dark_mode else "#2d2d2d"

        tk.Label(notice_frame, text="新增&修复 功能",
                 font=("微软雅黑", 16, "bold"), bg=frame_bg,
                 fg=self.primary_color).pack(pady=(18, 12), anchor="w", padx=25)

        version_data = [
            {
                "ver": "v2.2.4",
                "content": [
                    "1. 首页优化为可用滚轮滑动的长界面",
                    "2. 更改了工具栏展开的逻辑，现在展开不会再压缩工具界面",
                    "3. 优化工具栏的展开效果，现在更加丝滑"
                ]
            },
            {
                "ver": "v2.2.3",
                "content": [
                    "1. 增强计算器功能，支持复杂数学运算、科学计算、进制转换。"
                ]
            },
            {
                "ver": "v2.2.2",
                "content": [
                    "1. 修复快捷键无法使用的问题，更换为F功能键。",
                    "2. 完善漂浮字幕功能，优化显示效果。"
                ]
            },
            {
                "ver": "v2.2.1",
                "content": [
                    "1. 界面与功能细节优化。"
                ]
            },
            {
                "ver": "v2.1.n",
                "content": [
                    "1. 新增鼠标连点器功能。",
                    "2. 新增自定义漂浮字幕功能。",
                    "3. 优化整体UI与使用体验。"
                ]
            },

            {
                "ver": "V2.0.n",
                "content": [
                    "1. 将原来的粗糙界面更新为现在的简约风格",
                    "2. 新增主页、网页导航、计算器、支持根号七四个功能",
                    "3. 新增工具栏折叠状态，以及平移动画",
                    "4. 优化整体UI与使用体验。"
                ]
            },
            {
                "ver": "V1 完结！",
                "content": [
                    "1. 已打包",
                    "2. 太垃圾了，就不让大家看了"
                ]
            },
            {
                "ver": "V1.1",
                "content": [
                    "1. 将背景变为渐变风格",
                    "2. 新增第二个按钮“暂无更多”",
                    "3. 新增进群、b站关注功能"
                ]
            },
            {
                "ver": "V1.0",
                "content": [
                    "1. “写”下第一个代码",
                    "2. 新增第一个按钮“打开bilibili网站”",
                    "3. 新增赞赏功能"
                ]
            },
            {
                "ver": "制作之前",
                "content": [
                    "1. 梦想做一个爆火的工具箱",
                    "2. B站寻找Python教程",
                    "3. 下载豆包，全程指挥豆包给我写代码"
                ]
            },
            {
                "ver": "暂无更多历史记录",
                "content": [
                    "谢谢你能耐心地看到这里",
                    "有没有建议什么想对我说的呢？",
                    "左侧工具栏点击“支持根号七”通过第二栏进群，或通过第三栏找到我的B站账号，以提交意见",
                    ""
                ]
            }
        ]

        for item in version_data:
            tk.Label(notice_frame, text=item["ver"],
                     font=("微软雅黑", 13, "bold"), bg=frame_bg,
                     fg=self.primary_color).pack(anchor="w", padx=30, pady=(8, 4))
            for txt in item["content"]:
                tk.Label(notice_frame, text=txt,
                         font=("微软雅黑", 11), bg=frame_bg,
                         fg=self.text_color, justify="left").pack(anchor="w", padx=45, pady=2)

        tk.Label(content_frame, text="该应用由 三分之根号七 制作",
                 font=("微软雅黑", 24, "bold"), bg=self.bg_color,
                 fg=self.primary_color).pack(pady=20)

        return frame

    def preload_page_nav(self, parent):
        """预加载网址导航页"""
        frame = tk.Frame(parent, bg=self.bg_color)

        tk.Label(frame, text="🧭 网址导航", font=("微软雅黑", 22, "bold"), bg=self.bg_color,
                 fg=self.primary_color).pack(pady=(10, 5), anchor="w")
        tk.Label(frame, text="网址为作者推荐", font=("微软雅黑", 10), bg=self.bg_color, fg="#9CA3AF").pack(
            pady=(0, 20), anchor="w")

        search_frame = tk.Frame(frame, bg=self.bg_color)
        search_frame.pack(fill=tk.X, pady=10)
        search_engine = tk.StringVar(value="百度")
        engine_combobox = ttk.Combobox(search_frame, textvariable=search_engine,
                                       values=["百度", "必应", "搜狗", "哔哩哔哩 搜视频"],
                                       state="readonly", width=10, font=("微软雅黑", 24))
        engine_combobox.pack(side=tk.LEFT, padx=5)

        def search():
            query = self.search_entry.get().strip()
            if not query or query == "输入搜索内容":
                messagebox.showwarning("提示", "请输入搜索内容")
                return
            engine = search_engine.get()
            url_map = {
                "百度": f"https://www.baidu.com/s?wd={query}",
                "必应": f"https://cn.bing.com/search?q={query}",
                "搜狗": f"https://www.sogou.com/web?query={query}",
                "哔哩哔哩 搜视频": f"https://search.bilibili.com/all?keyword={query}"
            }
            webbrowser.open_new_tab(url_map[engine])

        search_btn = tk.Button(search_frame, text="搜索", font=("微软雅黑", 15, "bold"),
                               bg=self.button_bg, fg="white", relief=tk.FLAT, command=search)
        search_btn.pack(side=tk.RIGHT, padx=5)

        self.search_entry = tk.Entry(search_frame, font=("微软雅黑", 24))
        self.search_entry.pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True, ipady=2)
        self.search_entry.insert(0, "输入搜索内容")
        self.search_entry.bind("<Return>", lambda e: search())

        website_list = [
            ("哔哩哔哩", "https://www.bilibili.com"),
            ("抖音", "https://www.douyin.com"),
            ("豆包", "https://www.doubao.com"),
            ("Deepseek", "https://www.deepseek.com"),
            ("CCTV", "https://www.cctv.com"),
            ("MBTI测试", "https://www.jyshare.com/front-end/10312/"),
            ("B站关注", "https://space.bilibili.com/3493288684292639")
        ]
        btn_container = tk.Frame(frame, bg=self.bg_color)
        btn_container.pack(fill=tk.BOTH, expand=True)

        def open_website(site_name, site_url):
            if messagebox.askyesno("导航提示", f"是否打开【{site_name}】官网？"):
                try:
                    webbrowser.open_new_tab(site_url)
                except Exception as e:
                    messagebox.showerror("跳转失败", f"打开网站失败：{str(e)}")

        col_count = 7
        for index, (site_name, site_url) in enumerate(website_list):
            row = index // col_count
            col = index % col_count
            nav_btn = tk.Button(btn_container, text=site_name,
                                command=lambda name=site_name, url=site_url: open_website(name, url),
                                width=16, font=("微软雅黑", 14), bg=self.button_bg,
                                fg="white", relief=tk.FLAT, cursor="hand2")
            nav_btn.grid(row=row, column=col, padx=6, pady=6, sticky="nsew")
        for col in range(col_count):
            btn_container.grid_columnconfigure(col, weight=1)

        return frame

    def preload_page_calculator(self, parent):
        """预加载计算器页"""
        frame = tk.Frame(parent, bg=self.bg_color)
        self.calc_expression = ""

        main_container = tk.Frame(frame, bg=self.bg_color)
        main_container.pack(fill=tk.BOTH, expand=True)

        calc_frame = tk.Frame(main_container, bg=self.bg_color)
        calc_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 15))

        tk.Label(calc_frame, text="🧮 计算器", font=("微软雅黑", 20, "bold"), bg=self.bg_color,
                 fg=self.primary_color).pack(pady=(0, 15), anchor="w")

        self.calc_mode = tk.StringVar(value="普通模式")
        mode_box = ttk.Combobox(calc_frame, textvariable=self.calc_mode,
                                values=["普通模式", "科学模式"], state="readonly", width=12)
        mode_box.pack(anchor="w", pady=5)
        mode_box.bind("<<ComboboxSelected>>", lambda e: self.refresh_calc_buttons())

        self.calc_display = tk.Entry(calc_frame, font=("微软雅黑", 24), justify="right", bd=10,
                                     bg="#2d2d2d" if self.is_dark_mode else "white",
                                     fg="white" if self.is_dark_mode else self.text_color,
                                     relief=tk.FLAT)
        self.calc_display.pack(fill=tk.X, pady=10, ipady=15)

        self.btn_frame = tk.Frame(calc_frame, bg=self.bg_color)
        self.btn_frame.pack(fill=tk.BOTH, expand=True, pady=10)

        self.refresh_calc_buttons()

        right_frame = tk.Frame(main_container, bg="white" if not self.is_dark_mode else "#2d2d2d",
                               bd=2, relief=tk.RIDGE, width=280)
        right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=False, padx=(15, 0))
        right_frame.pack_propagate(False)

        frame_bg = "white" if not self.is_dark_mode else "#2d2d2d"

        tk.Label(right_frame, text="🔢 进制转换", font=("微软雅黑", 12, "bold"),
                 bg=frame_bg, fg=self.primary_color).pack(pady=10)
        self.dec_var = tk.StringVar()
        self.bin_var = tk.StringVar()
        self.oct_var = tk.StringVar()
        self.hex_var = tk.StringVar()

        for txt, var in [("十进制:", self.dec_var), ("二进制:", self.bin_var), ("八进制:", self.oct_var),
                         ("十六进制:", self.hex_var)]:
            row = tk.Frame(right_frame, bg=frame_bg)
            row.pack(fill=tk.X, padx=10, pady=2)
            tk.Label(row, text=txt, bg=frame_bg, fg=self.text_color, width=8, anchor="w").pack(side=tk.LEFT)
            ent = tk.Entry(row, textvariable=var, font=("微软雅黑", 10))
            ent.pack(side=tk.LEFT, fill=tk.X, expand=True)
            ent.bind("<Return>", lambda e: self.convert_base())

        ttk.Button(right_frame, text="一键转换", command=self.convert_base, style="Primary.TButton").pack(pady=8,
                                                                                                          padx=10,
                                                                                                          fill=tk.X)
        ttk.Button(right_frame, text="清空进制", command=self.clear_base, style="Primary.TButton").pack(pady=4, padx=10,
                                                                                                        fill=tk.X)

        tk.Label(right_frame, text="📝 计算历史记录", font=("微软雅黑", 12, "bold"),
                 bg=frame_bg, fg=self.primary_color).pack(pady=15)
        self.history_display = scrolledtext.ScrolledText(right_frame, font=("微软雅黑", 10), wrap=tk.WORD,
                                                         bg="#F8FAFC" if not self.is_dark_mode else "#1e1e1e",
                                                         fg=self.text_color, state=tk.DISABLED)
        self.history_display.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)

        def clear_calc_history():
            self.calc_history = []
            self.update_history_display()

        ttk.Button(right_frame, text="清空历史记录", command=clear_calc_history, style="Primary.TButton").pack(pady=10,
                                                                                                               padx=10,
                                                                                                               fill=tk.X)
        self.update_history_display()

        return frame

    def refresh_calc_buttons(self):
        for w in self.btn_frame.winfo_children():
            w.destroy()
        mode = self.calc_mode.get()
        if mode == "普通模式":
            buttons = [
                ("C", 0, 0, "#EF4444", "white"), ("←", 0, 1, "#F59E0B", "white"), ("%", 0, 2, "#F59E0B", "white"),
                ("÷", 0, 3, "#F59E0B", "white"),
                ("7", 1, 0, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("8", 1, 1, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("9", 1, 2, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("×", 1, 3, "#F59E0B", "white"),
                ("4", 2, 0, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("5", 2, 1, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("6", 2, 2, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("-", 2, 3, "#F59E0B", "white"),
                ("1", 3, 0, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("2", 3, 1, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("3", 3, 2, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("+", 3, 3, "#F59E0B", "white"),
                ("00", 4, 0, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("0", 4, 1, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                (".", 4, 2, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("=", 4, 3, self.button_bg, "white"),
            ]
        else:
            buttons = [
                ("sin", 0, 0, "#3d3d3d" if self.is_dark_mode else "#E9E9E9", "white" if self.is_dark_mode else "#333"),
                ("cos", 0, 1, "#3d3d3d" if self.is_dark_mode else "#E9E9E9", "white" if self.is_dark_mode else "#333"),
                ("tan", 0, 2, "#3d3d3d" if self.is_dark_mode else "#E9E9E9", "white" if self.is_dark_mode else "#333"),
                ("π", 0, 3, "#3d3d3d" if self.is_dark_mode else "#E9E9E9", "white" if self.is_dark_mode else "#333"),
                ("√", 1, 0, "#3d3d3d" if self.is_dark_mode else "#E9E9E9", "white" if self.is_dark_mode else "#333"),
                ("x²", 1, 1, "#3d3d3d" if self.is_dark_mode else "#E9E9E9", "white" if self.is_dark_mode else "#333"),
                ("x³", 1, 2, "#3d3d3d" if self.is_dark_mode else "#E9E9E9", "white" if self.is_dark_mode else "#333"),
                ("e", 1, 3, "#3d3d3d" if self.is_dark_mode else "#E9E9E9", "white" if self.is_dark_mode else "#333"),
                ("(", 2, 0, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                (")", 2, 1, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("!", 2, 2, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("/", 2, 3, "#F59E0B", "white"),
                ("7", 3, 0, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("8", 3, 1, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("9", 3, 2, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("×", 3, 3, "#F59E0B", "white"),
                ("4", 4, 0, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("5", 4, 1, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("6", 4, 2, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("-", 4, 3, "#F59E0B", "white"),
                ("1", 5, 0, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("2", 5, 1, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("3", 5, 2, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("+", 5, 3, "#F59E0B", "white"),
                ("C", 6, 0, "#EF4444", "white"), ("←", 6, 1, "#F59E0B", "white"),
                ("0", 6, 2, "#2d2d2d" if self.is_dark_mode else "white",
                 "white" if self.is_dark_mode else self.text_color),
                ("=", 6, 3, self.button_bg, "white"),
            ]
        for text, row, col, bg, fg in buttons:
            btn = tk.Button(self.btn_frame, text=text, font=("微软雅黑", 12, "bold"), bg=bg, fg=fg, bd=0,
                            relief=tk.FLAT,
                            command=lambda t=text: self.calc_btn_click(t))
            btn.grid(row=row, column=col, padx=3, pady=3, sticky="nsew")
        max_row = max(b[1] for b in buttons)
        max_col = max(b[2] for b in buttons)
        for i in range(max_row + 1):
            self.btn_frame.grid_rowconfigure(i, weight=1)
        for i in range(max_col + 1):
            self.btn_frame.grid_columnconfigure(i, weight=1)

    def calc_btn_click(self, value):
        import math
        if value == "C":
            self.calc_expression = ""
            self.calc_display.delete(0, tk.END)
        elif value == "←":
            self.calc_expression = self.calc_expression[:-1]
            self.calc_display.delete(0, tk.END)
            self.calc_display.insert(tk.END, self.calc_expression)
        elif value == "=":
            self.calc_result()
        elif value == "π":
            self.calc_expression += str(math.pi)
        elif value == "e":
            self.calc_expression += str(math.e)
        elif value == "√":
            self.calc_expression += "math.sqrt("
        elif value == "x²":
            self.calc_expression += "**2"
        elif value == "x³":
            self.calc_expression += "**3"
        elif value == "sin":
            self.calc_expression += "math.sin(math.radians("
        elif value == "cos":
            self.calc_expression += "math.cos(math.radians("
        elif value == "tan":
            self.calc_expression += "math.tan(math.radians("
        elif value == "!":
            self.calc_expression += "math.factorial("
        else:
            self.calc_expression += value
        self.calc_display.delete(0, tk.END)
        self.calc_display.insert(tk.END, self.calc_expression)

    def is_valid_expression(self, exp):
        if not exp:
            return False
        if exp[0] in "+×÷%.)" or exp[-1] in "+-×÷%.(":
            return False
        invalid = ["++", "+-", "+×", "+÷", "-+", "--", "-×", "-÷", "×+", "×-", "××", "×÷", "÷+", "÷-", "÷×", "÷÷", ".."]
        for s in invalid:
            if s in exp:
                return False
        return True

    def calc_result(self):
        import math
        if not self.is_valid_expression(self.calc_expression):
            self.calc_display.delete(0, tk.END)
            self.calc_display.insert(tk.END, "表达式错误")
            self.calc_expression = ""
            return
        try:
            expr = self.calc_expression.replace("×", "*").replace("÷", "/")
            res = eval(expr, {"__builtins__": None, "math": math})
            if isinstance(res, float) and res.is_integer():
                res = int(res)
            self.calc_history.append(f"{self.calc_expression} = {res}")
            self.update_history_display()
            self.calc_display.delete(0, tk.END)
            self.calc_display.insert(tk.END, str(res))
            self.calc_expression = str(res)
        except ZeroDivisionError:
            self.calc_display.delete(0, tk.END)
            self.calc_display.insert(tk.END, "除数不能为0")
            self.calc_expression = ""
        except:
            self.calc_display.delete(0, tk.END)
            self.calc_display.insert(tk.END, "表达式错误")
            self.calc_expression = ""

    def convert_base(self):
        try:
            dec = int(self.dec_var.get().strip())
            self.bin_var.set(bin(dec)[2:])
            self.oct_var.set(oct(dec)[2:])
            self.hex_var.set(hex(dec)[2:].upper())
        except:
            pass

    def clear_base(self):
        self.dec_var.set("")
        self.bin_var.set("")
        self.oct_var.set("")
        self.hex_var.set("")

    def update_history_display(self):
        self.history_display.config(state=tk.NORMAL)
        self.history_display.delete(1.0, tk.END)
        for item in reversed(self.calc_history):
            self.history_display.insert(tk.END, f"▶ {item}\n\n")
        self.history_display.config(state=tk.DISABLED)

    def preload_page_clicker(self, parent):
        """预加载连点器页面"""
        frame = tk.Frame(parent, bg=self.bg_color)

        tk.Label(frame, text="🖱 鼠标指针辅助器", font=("微软雅黑", 22, "bold"),
                 bg=self.bg_color, fg=self.primary_color).pack(pady=(10, 20), anchor="w")

        setting_frame = tk.Frame(frame, bg="white" if not self.is_dark_mode else "#2d2d2d", bd=2, relief=tk.RIDGE)
        setting_frame.pack(fill=tk.X, padx=0, pady=5)
        inner = tk.Frame(setting_frame, bg="white" if not self.is_dark_mode else "#2d2d2d")
        inner.pack(padx=20, pady=18)

        label_bg = "white" if not self.is_dark_mode else "#2d2d2d"
        label_fg = self.text_color

        tk.Label(inner, text="点击间隔(ms)：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).grid(row=0, column=0,
                                                                                                    sticky="w", padx=5)
        self.click_interval = tk.Entry(inner, font=("微软雅黑", 12), width=8)
        self.click_interval.grid(row=0, column=1, padx=5)
        self.click_interval.insert(0, "100")

        tk.Label(inner, text="点击次数(-1无限)：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).grid(row=0, column=2,
                                                                                                        sticky="w",
                                                                                                        padx=5)
        self.click_times = tk.Entry(inner, font=("微软雅黑", 12), width=8)
        self.click_times.grid(row=0, column=3, padx=5)
        self.click_times.insert(0, "-1")

        tk.Label(inner, text="鼠标按键：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).grid(row=1, column=0,
                                                                                                sticky="w", pady=12)
        self.click_btn = tk.StringVar(value="左键")
        ttk.Combobox(inner, textvariable=self.click_btn, values=["左键", "右键"], state="readonly", width=7).grid(row=1,
                                                                                                                  column=1)

        tk.Label(inner, text="点击模式：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).grid(row=1, column=2,
                                                                                                sticky="w")
        self.click_mode = tk.StringVar(value="单击")
        ttk.Combobox(inner, textvariable=self.click_mode, values=["单击", "双击"], state="readonly", width=7).grid(
            row=1, column=3)

        btn_frame = tk.Frame(frame, bg=self.bg_color)
        btn_frame.pack(pady=12)

        tk.Button(btn_frame, text="▶ 启动连点", font=("微软雅黑", 12, "bold"),
                  bg="#1F7A48", fg="white", relief=tk.FLAT, padx=18, pady=6,
                  command=self.start_clicker).grid(row=0, column=0, padx=8)

        tk.Button(btn_frame, text="⏹ 停止连点", font=("微软雅黑", 12, "bold"),
                  bg="#dc2626", fg="white", relief=tk.FLAT, padx=18, pady=6,
                  command=self.stop_clicker).grid(row=0, column=1, padx=8)

        self.click_status = tk.Label(frame, text="状态：已停止", font=("微软雅黑", 13),
                                     bg=self.bg_color, fg=self.text_color)
        self.click_status.pack(pady=4)

        hk_frame = tk.Frame(frame, bg=self.bg_color)
        hk_frame.pack(pady=4)
        self.clicker_hk_label = tk.Label(hk_frame, text=f"快捷键：{self.shortcuts['clicker_toggle']} 切换启动/停止",
                                         font=("微软雅黑", 12), bg=self.bg_color, fg=self.text_color)
        self.clicker_hk_label.pack(side=tk.LEFT)
        tk.Checkbutton(hk_frame, text="启用快捷键", variable=self.hotkey_enabled,
                       bg=self.bg_color, font=("微软雅黑", 11)).pack(side=tk.LEFT, padx=8)

        return frame

    def preload_page_float_text(self, parent):
        """预加载漂浮字幕页"""
        frame = tk.Frame(parent, bg=self.bg_color)

        tk.Label(frame, text="📝 自定义漂浮字幕", font=("微软雅黑", 22, "bold"),
                 bg=self.bg_color, fg=self.primary_color).pack(pady=(10, 20), anchor="w")

        main_panel = tk.Frame(frame, bg=self.bg_color)
        main_panel.pack(fill=tk.BOTH, expand=True, padx=0, pady=5)

        setting_frame = tk.Frame(main_panel, bg="white" if not self.is_dark_mode else "#2d2d2d", bd=2, relief=tk.RIDGE)
        setting_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=0, pady=0)
        inner = tk.Frame(setting_frame, bg="white" if not self.is_dark_mode else "#2d2d2d")
        inner.pack(padx=20, pady=18, fill=tk.X)

        label_bg = "white" if not self.is_dark_mode else "#2d2d2d"
        label_fg = self.text_color

        tk.Label(inner, text="字幕内容：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).grid(row=0, column=0,
                                                                                                sticky="w", padx=5,
                                                                                                pady=5)
        self.float_text_entry = tk.Text(inner, font=("微软雅黑", 12), width=30, height=3, wrap=tk.WORD,
                                        bg="#f8f8f8" if not self.is_dark_mode else "#1e1e1e",
                                        fg=self.text_color, insertbackground=self.text_color)
        self.float_text_entry.grid(row=0, column=1, columnspan=3, padx=5, pady=5, sticky="ew")
        self.float_text_entry.insert("1.0", "点击修改漂浮字幕")

        tk.Label(inner, text="横向坐标：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).grid(row=1, column=0,
                                                                                                sticky="w", padx=5,
                                                                                                pady=5)
        self.float_x_entry = tk.Entry(inner, font=("微软雅黑", 12), width=10)
        self.float_x_entry.grid(row=1, column=1, padx=5, pady=5)
        self.float_x_entry.insert(0, "100")

        tk.Label(inner, text="纵向坐标：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).grid(row=1, column=2,
                                                                                                sticky="w", padx=5,
                                                                                                pady=5)
        self.float_y_entry = tk.Entry(inner, font=("微软雅黑", 12), width=10)
        self.float_y_entry.grid(row=1, column=3, padx=5, pady=5)
        self.float_y_entry.insert(0, "100")

        tk.Label(inner, text="文本大小：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).grid(row=2, column=0,
                                                                                                sticky="w", padx=5,
                                                                                                pady=5)
        self.float_size_entry = tk.Entry(inner, font=("微软雅黑", 12), width=10)
        self.float_size_entry.grid(row=2, column=1, padx=5, pady=5)
        self.float_size_entry.insert(0, "24")

        tk.Label(inner, text="文本字体：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).grid(row=3, column=0,
                                                                                                sticky="w", padx=5,
                                                                                                pady=5)
        self.float_font_entry = tk.Entry(inner, font=("微软雅黑", 12), width=10)
        self.float_font_entry.grid(row=3, column=1, padx=5, pady=5)
        self.float_font_entry.insert(0, "微软雅黑")

        tk.Label(inner, text="文本颜色：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).grid(row=4, column=0,
                                                                                                sticky="w", padx=5,
                                                                                                pady=5)
        self.color_btn = tk.Button(inner, text="选择颜色", command=self.choose_float_color, bg="#ff0000", fg="white",
                                   font=("微软雅黑", 10))
        self.color_btn.grid(row=4, column=1, padx=5, pady=5)

        tk.Label(inner, text="背景颜色：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).grid(row=5, column=0,
                                                                                                sticky="w", padx=5,
                                                                                                pady=5)
        self.bg_color_btn = tk.Button(inner, text="选择颜色", command=self.choose_float_bg_color, bg="#00FF00",
                                      fg="white", font=("微软雅黑", 10))
        self.bg_color_btn.grid(row=5, column=1, padx=5, pady=5)

        tk.Label(inner, text="透明度：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).grid(row=6, column=0,
                                                                                              sticky="w", padx=5,
                                                                                              pady=5)
        self.alpha_scale = tk.Scale(inner, from_=1, to=100, variable=self.float_alpha, orient=tk.HORIZONTAL,
                                    bg=label_bg)
        self.alpha_scale.grid(row=6, column=1, columnspan=3, sticky="ew", padx=5, pady=5)
        self.alpha_scale.set(100)

        tk.Label(inner, text="预设：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).grid(row=7, column=0, sticky="w",
                                                                                            padx=5, pady=8)

        def preset1():
            self.float_text_entry.delete("1.0", tk.END)
            self.float_text_entry.insert("1.0", "现在时间：{year}年{month}月{day}日 {hour}:{minute}:{second}")

        def preset2():
            self.float_text_entry.delete("1.0", tk.END)
            self.float_text_entry.insert("1.0", "默认文本")

        ttk.Button(inner, text="当前时间", command=preset1).grid(row=7, column=1, padx=3, pady=8)
        ttk.Button(inner, text="暂无更多", command=preset2).grid(row=7, column=2, padx=3, pady=8)

        help_frame = tk.Frame(main_panel, bg="white" if not self.is_dark_mode else "#2d2d2d", bd=2, relief=tk.RIDGE)
        help_frame.pack(side=tk.RIGHT, padx=(10, 0), fill=tk.Y)
        tk.Label(help_frame, text="📌 变量使用说明", font=("微软雅黑", 14, "bold"),
                 bg=label_bg, fg=self.primary_color).pack(pady=(15, 10), padx=15)
        help_text = """输入以下内容可自动显示：
{year}   →  当前年份
{month}  →  当前月份
{day}   →  今日日期
{hour}   →  当前小时
{minute} →  当前分钟
{second} →  当前秒数
{math:表达式} → 计算结果
\\n → 换行"""
        tk.Label(help_frame, text=help_text, justify=tk.LEFT, font=("微软雅黑", 11),
                 bg=label_bg, fg=self.text_color).pack(anchor="w", padx=15, pady=5)

        btn_frame = tk.Frame(frame, bg=self.bg_color)
        btn_frame.pack(pady=12)
        tk.Button(btn_frame, text="💬 显示字幕", font=("微软雅黑", 12, "bold"),
                  bg="#1F7A48", fg="white", relief=tk.FLAT, padx=18, pady=6,
                  command=self.show_float_text).grid(row=0, column=0, padx=8)
        tk.Button(btn_frame, text="❌ 隐藏字幕", font=("微软雅黑", 12, "bold"),
                  bg="#dc2626", fg="white", relief=tk.FLAT, padx=18, pady=6,
                  command=self.hide_float_text).grid(row=0, column=1, padx=8)

        self.float_status = tk.Label(frame, text="状态：已停止", font=("微软雅黑", 13),
                                     bg=self.bg_color, fg=self.text_color)
        self.float_status.pack(pady=4)

        float_hk_frame = tk.Frame(frame, bg=self.bg_color)
        float_hk_frame.pack(pady=4)
        self.float_hk_label = tk.Label(float_hk_frame, text=f"快捷键：{self.shortcuts['float_toggle']} 切换显示/隐藏",
                                       font=("微软雅黑", 12), bg=self.bg_color, fg=self.text_color)
        self.float_hk_label.pack(side=tk.LEFT)
        tk.Checkbutton(float_hk_frame, text="启用快捷键", variable=self.float_hotkey_enabled,
                       bg=self.bg_color, font=("微软雅黑", 11)).pack(side=tk.LEFT, padx=8)

        return frame

    def choose_float_color(self):
        color = colorchooser.askcolor(title="选择文字颜色")[1]
        if color:
            self.float_color = color
            self.color_btn.config(bg=color)

    def choose_float_bg_color(self):
        color = colorchooser.askcolor(title="选择背景颜色")[1]
        if color:
            self.float_bg_color = color
            self.bg_color_btn.config(bg=color)

    def show_float_text(self):
        if self.float_window:
            self.float_window.destroy()

        try:
            self.float_x = int(self.float_x_entry.get())
            self.float_y = int(self.float_y_entry.get())
            self.float_font_size = int(self.float_size_entry.get())
            self.float_font_family = self.float_font_entry.get().strip()
        except ValueError:
            messagebox.showwarning("输入错误", "坐标和字体大小必须为数字")
            return

        self.float_window = tk.Toplevel(self.root)
        self.float_window.overrideredirect(True)
        self.float_window.geometry(f"+{self.float_x}+{self.float_y}")
        self.float_window.attributes("-topmost", True)
        self.float_window.attributes("-alpha", self.float_alpha.get() / 100)
        self.float_window.config(bg=self.float_bg_color)

        raw_text = self.float_text_entry.get("1.0", tk.END).strip()
        real_txt = self.parse_float_text(raw_text)

        self.float_label = tk.Label(self.float_window, text=real_txt,
                                    font=(self.float_font_family, self.float_font_size, "bold"),
                                    fg=self.float_color, bg=self.float_bg_color)
        self.float_label.pack()

        self.float_window.update()
        self.float_auto_refresh()

        self.float_running = True
        self.float_status.config(text="状态：运行中", fg="#e53e3e")

    def hide_float_text(self):
        if self.float_refresh_id:
            self.root.after_cancel(self.float_refresh_id)
            self.float_refresh_id = None
        if self.float_window:
            self.float_window.destroy()
            self.float_window = None
            self.float_label = None

        self.float_running = False
        self.float_status.config(text="状态：已停止", fg=self.text_color)

    def preload_page_weather(self, parent):
        """预加载天气预报页"""
        frame = tk.Frame(parent, bg=self.bg_color)

        title_label = tk.Label(
            frame, text="🌤 天气预报",
            font=("微软雅黑", 22, "bold"),
            bg=self.bg_color, fg=self.primary_color
        )
        title_label.pack(pady=(10, 20), anchor="w", padx=10)

        main_container = tk.Frame(frame, bg=self.bg_color)
        main_container.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)

        current_card = tk.Frame(main_container, bg="white" if not self.is_dark_mode else "#2d2d2d", bd=1,
                                relief=tk.RIDGE)
        current_card.pack(fill=tk.X, pady=(0, 15))

        card_title = tk.Label(
            current_card, text="实时天气",
            font=("微软雅黑", 16, "bold"),
            bg="white" if not self.is_dark_mode else "#2d2d2d",
            fg=self.primary_color
        )
        card_title.pack(pady=10, anchor="w", padx=15)

        self.weather_content = tk.Frame(current_card, bg="white" if not self.is_dark_mode else "#2d2d2d")
        self.weather_content.pack(fill=tk.BOTH, expand=True, padx=15, pady=10)

        future_title = tk.Label(
            main_container, text="📅 未来7天预报",
            font=("微软雅黑", 16, "bold"),
            bg=self.bg_color, fg=self.primary_color
        )
        future_title.pack(anchor="w", padx=10, pady=(0, 10))

        self.future_container = tk.Frame(main_container, bg=self.bg_color)
        self.future_container.pack(fill=tk.BOTH, expand=True, padx=5)

        refresh_btn = ttk.Button(
            frame, text="🔄 刷新天气", style="Primary.TButton",
            command=lambda: threading.Thread(target=self.get_weather, daemon=True).start()
        )
        refresh_btn.pack(pady=10)

        # 异步获取天气
        threading.Thread(target=self.get_weather, daemon=True).start()

        return frame

    def get_weather(self):
        try:
            g = geocoder.ip("me")
            if not g.ok:
                raise Exception("定位失败")

            lat, lng = g.latlng
            city_cn = g.city
            numbered_print(f"[{get_time_str()}] 当前定位城市：{city_cn}")

            url = (
                f"https://api.open-meteo.com/v1/forecast?"
                f"latitude={lat}&longitude={lng}&"
                f"current_weather=true&"
                f"daily=weathercode,temperature_2m_max,temperature_2m_min&"
                f"timezone=auto"
            )
            res = requests.get(url, timeout=8)
            data = res.json()
            data["city_cn"] = city_cn
            self.weather_cache = data

            numbered_print(f"[{get_time_str()}] 天气数据获取成功")
            self.root.after(0, lambda: self.show_weather(data))

        except Exception as e:
            numbered_print(f"[{get_time_str()}] 天气获取失败：{e}")
            self.root.after(0, lambda: self.show_weather_error(f"获取失败：{str(e)}"))

    def show_weather(self, data):
        try:
            for widget in self.weather_content.winfo_children():
                widget.destroy()
            for widget in self.future_container.winfo_children():
                widget.destroy()
        except:
            return

        code_map = {
            0: ("☀", "晴天"), 1: ("⛅", "多云"), 2: ("🌤", "少云"), 3: ("☁", "阴天"),
            45: ("🌫", "雾"), 48: ("🌨", "雾凇"),
            51: ("🌧", "小雨"), 53: ("🌧", "中雨"), 55: ("🌧", "大雨"),
            61: ("🌦", "阵雨"), 63: ("🌦", "强阵雨"),
            71: ("❄", "小雪"), 73: ("❄", "中雪"), 75: ("❄", "大雪"),
            80: ("⛈", "雷阵雨"), 81: ("⛈", "强雷阵雨"), 95: ("⛈", "雷暴")
        }

        city_cn = data.get("city_cn")
        curr = data["current_weather"]
        w_emoji, w_text = code_map.get(curr["weathercode"], ("❓", "未知"))

        info_grid = tk.Frame(self.weather_content, bg="white" if not self.is_dark_mode else "#2d2d2d")
        info_grid.pack(fill=tk.BOTH, expand=True)

        frame_bg = "white" if not self.is_dark_mode else "#2d2d2d"

        tk.Label(info_grid, text=f"📍 城市：{city_cn}", font=("微软雅黑", 14),
                 bg=frame_bg, fg=self.text_color).grid(row=0, column=0, sticky="w", padx=20, pady=8)
        tk.Label(info_grid, text=f"{w_emoji} {w_text}", font=("微软雅黑", 14),
                 bg=frame_bg, fg=self.text_color).grid(row=0, column=1, sticky="w", padx=20, pady=8)
        tk.Label(info_grid, text=f"🌡️ 温度：{curr['temperature']}℃", font=("微软雅黑", 14),
                 bg=frame_bg, fg=self.text_color).grid(row=1, column=0, sticky="w", padx=20, pady=8)
        tk.Label(info_grid, text=f"💨 风速：{curr['windspeed']} km/h", font=("微软雅黑", 14),
                 bg=frame_bg, fg=self.text_color).grid(row=1, column=1, sticky="w", padx=20, pady=8)

        daily = data["daily"]
        for i in range(7):
            day_card = tk.Frame(self.future_container, bg=frame_bg, bd=1, relief=tk.RIDGE, padx=10, pady=10)
            day_card.grid(row=0, column=i, padx=5, pady=5, sticky="nsew")
            date = daily["time"][i].replace("2026-", "")
            tk.Label(day_card, text=date, font=("微软雅黑", 12, "bold"),
                     bg=frame_bg, fg=self.primary_color).pack(pady=5)
            d_emoji, d_text = code_map.get(daily["weathercode"][i], ("❓", "未知"))
            tk.Label(day_card, text=d_emoji, font=("微软雅黑", 20),
                     bg=frame_bg, fg=self.text_color).pack(pady=3)
            tk.Label(day_card, text=d_text, font=("微软雅黑", 10),
                     bg=frame_bg, fg="#666" if not self.is_dark_mode else "#aaa").pack(pady=2)
            temp_range = f"{daily['temperature_2m_min'][i]}~{daily['temperature_2m_max'][i]}℃"
            tk.Label(day_card, text=temp_range, font=("微软雅黑", 11),
                     bg=frame_bg, fg=self.text_color).pack(pady=5)

        for i in range(7):
            self.future_container.grid_columnconfigure(i, weight=1)

    def show_weather_error(self, msg):
        try:
            for w in self.weather_content.winfo_children():
                w.destroy()
            tk.Label(self.weather_content, text=msg, font=("微软雅黑", 12),
                     bg="white" if not self.is_dark_mode else "#2d2d2d",
                     fg="red").pack(pady=30)
        except:
            return

    def preload_page_sign_fortune(self, parent):
        """预加载签到中心页"""
        frame = tk.Frame(parent, bg=self.bg_color)

        import datetime
        import random
        import json
        import os

        today = datetime.datetime.now()
        today_str = today.strftime("%Y-%m-%d")

        data_file = "sign_data.json"
        sign_data = {}
        streak = 0
        total_days = 0

        if os.path.exists(data_file):
            try:
                with open(data_file, 'r', encoding='utf-8') as f:
                    sign_data = json.load(f)
                    last_date = sign_data.get('last_sign_date', '')
                    if last_date:
                        last = datetime.datetime.strptime(last_date, "%Y-%m-%d")
                        delta = (today - last).days
                        if delta == 1:
                            streak = sign_data.get('streak', 0) + 1
                        elif delta == 0:
                            streak = sign_data.get('streak', 0)
                        else:
                            streak = 1
                    total_days = len(sign_data.get('signed_days', []))
            except:
                sign_data = {'signed_days': [], 'last_sign_date': '', 'streak': 0}
        else:
            sign_data = {'signed_days': [], 'last_sign_date': '', 'streak': 0}

        signed_days = set(sign_data.get('signed_days', []))
        is_signed_today = today_str in signed_days

        random.seed(int(today.strftime("%Y%m%d")))

        fortune_levels = ["大吉", "中吉", "小吉", "末吉", "平", "小凶", "中凶", "大凶"]
        weights = [5, 12, 18, 20, 25, 10, 6, 4]
        fortune = random.choices(fortune_levels, weights=weights)[0]

        lucky_num = random.randint(1, 99)
        colors = ["红色", "橙色", "黄色", "绿色", "青色", "蓝色", "紫色", "粉色", "白色", "金色", "银色"]
        lucky_color = random.choice(colors)
        directions = ["东", "南", "西", "北", "东南", "东北", "西南", "西北"]
        lucky_dir = random.choice(directions)
        zodiacs = ["白羊座", "金牛座", "双子座", "巨蟹座", "狮子座", "处女座", "天秤座", "天蝎座", "射手座", "摩羯座",
                   "水瓶座", "双鱼座"]
        lucky_zodiac = random.choice(zodiacs)

        fortune_texts = {
            "大吉": "万事如意，心想事成。", "中吉": "运势不错，努力会有回报。", "小吉": "小有收获，保持乐观。",
            "末吉": "平淡中藏机遇。", "平": "平稳的一天，适合休整。", "小凶": "稍有不顺，注意言行。",
            "中凶": "运势走低，低调行事。", "大凶": "诸事不宜，注意安全。"
        }

        fortune_symbol = {"大吉": "🎉", "中吉": "🍀", "小吉": "✨", "末吉": "🌱", "平": "⚖️", "小凶": "💫", "中凶": "🌙",
                          "大凶": "💢"}

        warm_words = [
            "愿你今天拥有好心情！", "生活就像一面镜子，你对它笑，它就对你笑。",
            "每一个今天都是余生中最年轻的一天。", "坚持下去，不是因为看到希望，而是因为相信希望。",
            "你比你想象的更有力量。", "今天也要元气满满哦！", "无论昨天如何，今天都是崭新的开始。",
            "好好爱自己，世界也会爱你。", "心存美好，遇见美好。", "你的努力，时间看得见。"
        ]
        warm_word = random.choice(warm_words)

        tips = {
            "大吉": "大胆行动，主动出击，今天成功率很高。",
            "中吉": "稳步前进，与人合作会有意外收获。",
            "小吉": "保持耐心，积少成多，下午运势更好。",
            "末吉": "放平心态，享受过程，结果顺其自然。",
            "平": "适合学习、整理、规划，不宜冒险。",
            "小凶": "谨言慎行，多听少说，避免冲突。",
            "中凶": "减少外出，重要物品保管好，注意健康。",
            "大凶": "今日宜静不宜动，重要决定改日再做。"
        }
        daily_tip = tips[fortune]

        good_things = ["社交", "学习", "运动", "工作", "约会", "购物", "旅行", "谈判", "创作", "理财"]
        bad_things = ["借贷", "投资", "签约", "出行", "搬家", "结婚", "开业", "诉讼"]

        if "大吉" in fortune:
            good_list = random.sample(good_things, 3)
            bad_list = random.sample(bad_things, 1)
        elif "中吉" in fortune:
            good_list = random.sample(good_things, 3)
            bad_list = random.sample(bad_things, 2)
        elif "小吉" in fortune:
            good_list = random.sample(good_things, 2)
            bad_list = random.sample(bad_things, 2)
        elif "凶" in fortune:
            good_list = random.sample(good_things, 1)
            bad_list = random.sample(bad_things, 3)
        else:
            good_list = random.sample(good_things, 2)
            bad_list = random.sample(bad_things, 2)

        main_container = tk.Frame(frame, bg=self.bg_color)
        main_container.pack(fill=tk.BOTH, expand=True)

        left_panel = tk.Frame(main_container, bg=self.bg_color)
        left_panel.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 10))

        right_panel = tk.Frame(main_container, bg="white" if not self.is_dark_mode else "#2d2d2d",
                               bd=2, relief=tk.RIDGE, width=300)
        right_panel.pack(side=tk.RIGHT, fill=tk.Y, padx=(10, 0))
        right_panel.pack_propagate(False)

        frame_bg = "white" if not self.is_dark_mode else "#2d2d2d"

        sign_card = tk.Frame(left_panel, bg=frame_bg, bd=2, relief=tk.RIDGE)
        sign_card.pack(fill=tk.X, pady=(0, 15))

        sign_inner = tk.Frame(sign_card, bg=frame_bg)
        sign_inner.pack(padx=20, pady=15, fill=tk.X)

        info_frame = tk.Frame(sign_inner, bg=frame_bg)
        info_frame.pack(fill=tk.X, pady=(0, 10))

        tk.Label(info_frame, text="📅 签到中心", font=("微软雅黑", 16, "bold"),
                 bg=frame_bg, fg=self.primary_color).pack(side=tk.LEFT)

        streak_label = tk.Label(info_frame, text=f"🔥 连续 {streak} 天",
                                font=("微软雅黑", 11, "bold"),
                                bg=frame_bg, fg="#F59E0B")
        streak_label.pack(side=tk.RIGHT)

        def do_sign():
            nonlocal is_signed_today, streak, total_days, signed_days
            if is_signed_today:
                messagebox.showinfo("提示", "今天已经签到过了！")
                return

            signed_days.add(today_str)
            streak += 1
            total_days = len(signed_days)

            sign_data['signed_days'] = list(signed_days)
            sign_data['last_sign_date'] = today_str
            sign_data['streak'] = streak

            with open(data_file, 'w', encoding='utf-8') as f:
                json.dump(sign_data, f, ensure_ascii=False)

            is_signed_today = True
            streak_label.config(text=f"🔥 连续 {streak} 天")
            sign_btn.config(text="✅ 今日已签到", state=tk.DISABLED, bg="#95A5A6")

            refresh_calendar()
            messagebox.showinfo("签到成功", f"签到成功！连续签到 {streak} 天")

        if is_signed_today:
            sign_btn = tk.Button(sign_inner, text="✅ 今日已签到", font=("微软雅黑", 13, "bold"),
                                 bg="#95A5A6", fg="white", state=tk.DISABLED, padx=20, pady=8)
        else:
            sign_btn = tk.Button(sign_inner, text="📝 立即签到", font=("微软雅黑", 13, "bold"),
                                 command=do_sign, bg=self.button_bg, fg="white", padx=20, pady=8)
        sign_btn.pack(pady=8)

        tk.Label(sign_inner, text=f"累计签到：{total_days} 天", font=("微软雅黑", 9),
                 bg=frame_bg, fg="#7F8C8D").pack()

        cal_card = tk.Frame(left_panel, bg=frame_bg, bd=2, relief=tk.RIDGE)
        cal_card.pack(fill=tk.BOTH, expand=True)

        cal_inner = tk.Frame(cal_card, bg=frame_bg)
        cal_inner.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        month_frame = tk.Frame(cal_inner, bg=frame_bg)
        month_frame.pack(fill=tk.X, pady=(0, 8))

        tk.Label(month_frame, text=f"{today.year}年{today.month}月",
                 font=("微软雅黑", 13, "bold"),
                 bg=frame_bg, fg=self.primary_color).pack()

        week_frame = tk.Frame(cal_inner, bg=frame_bg)
        week_frame.pack(fill=tk.X)
        weeks = ["日", "一", "二", "三", "四", "五", "六"]
        for w in weeks:
            color = "#E74C3C" if w == "日" or w == "六" else self.text_color
            tk.Label(week_frame, text=w, font=("微软雅黑", 10, "bold"),
                     bg=frame_bg, fg=color, width=4).pack(side=tk.LEFT, expand=True, fill=tk.X)

        cal_grid_container = tk.Frame(cal_inner, bg=frame_bg)
        cal_grid_container.pack(fill=tk.BOTH, expand=True)

        first_day = datetime.datetime(today.year, today.month, 1)
        start_weekday = first_day.weekday()
        start_weekday = (start_weekday + 1) % 7

        if today.month == 12:
            next_month = datetime.datetime(today.year + 1, 1, 1)
        else:
            next_month = datetime.datetime(today.year, today.month + 1, 1)
        days_in_month = (next_month - first_day).days

        def refresh_calendar():
            for widget in cal_grid_container.winfo_children():
                widget.destroy()

            day_num = 1
            cell_size = 48

            for row in range(6):
                row_frame = tk.Frame(cal_grid_container, bg=frame_bg, height=cell_size)
                row_frame.pack(fill=tk.X, pady=1)
                for col in range(7):
                    if row == 0 and col < start_weekday:
                        placeholder = tk.Frame(row_frame, width=cell_size, height=cell_size, bg=frame_bg)
                        placeholder.pack(side=tk.LEFT, expand=True, fill=tk.BOTH)
                    elif day_num <= days_in_month:
                        date_str = f"{today.year}-{today.month:02d}-{day_num:02d}"
                        is_signed = date_str in signed_days

                        canvas = tk.Canvas(row_frame, width=cell_size, height=cell_size, bg=frame_bg,
                                           highlightthickness=0)
                        canvas.pack(side=tk.LEFT, expand=True, fill=tk.BOTH)

                        if is_signed:
                            canvas.create_oval(4, 4, cell_size - 4, cell_size - 4,
                                               fill=self.button_bg, outline=self.button_bg)
                            canvas.create_text(cell_size // 2, cell_size // 2, text=str(day_num),
                                               font=("微软雅黑", 11, "bold"), fill="white")
                        else:
                            canvas.create_oval(4, 4, cell_size - 4, cell_size - 4,
                                               fill="#F0F0F0" if not self.is_dark_mode else "#3d3d3d",
                                               outline="#E0E0E0" if not self.is_dark_mode else "#555")
                            canvas.create_text(cell_size // 2, cell_size // 2, text=str(day_num),
                                               font=("微软雅黑", 11), fill=self.text_color)

                        if date_str == today_str:
                            canvas.create_oval(2, 2, cell_size - 2, cell_size - 2,
                                               outline=self.button_bg, width=2)

                        day_num += 1
                    else:
                        placeholder = tk.Frame(row_frame, width=cell_size, height=cell_size, bg=frame_bg)
                        placeholder.pack(side=tk.LEFT, expand=True, fill=tk.BOTH)

        refresh_calendar()

        fortune_panel = tk.Frame(right_panel, bg=frame_bg)
        fortune_panel.pack(fill=tk.BOTH, expand=True, padx=12, pady=12)

        tk.Label(fortune_panel, text=f"{fortune_symbol[fortune]} 今日运势 {fortune_symbol[fortune]}",
                 font=("微软雅黑", 14, "bold"), bg=frame_bg, fg=self.primary_color).pack(pady=(0, 8))

        tk.Label(fortune_panel, text=fortune, font=("微软雅黑", 24, "bold"),
                 bg=frame_bg, fg=self.primary_color).pack()

        tk.Label(fortune_panel, text=fortune_texts[fortune], font=("微软雅黑", 10),
                 bg=frame_bg, fg="#555" if not self.is_dark_mode else "#aaa",
                 wraplength=260, justify="center").pack(pady=8)

        tk.Frame(fortune_panel, bg="#E0E0E0" if not self.is_dark_mode else "#555", height=1).pack(fill=tk.X, pady=8)

        info_frame_right = tk.Frame(fortune_panel, bg=frame_bg)
        info_frame_right.pack(pady=8)

        tk.Label(info_frame_right, text=f"🔢 {lucky_num}   🎨 {lucky_color}", font=("微软雅黑", 10),
                 bg=frame_bg, fg="#E74C3C").pack(pady=2)
        tk.Label(info_frame_right, text=f"🧭 {lucky_dir}   ⭐ {lucky_zodiac}", font=("微软雅黑", 10),
                 bg=frame_bg, fg="#E74C3C").pack(pady=2)

        tk.Frame(fortune_panel, bg="#E0E0E0" if not self.is_dark_mode else "#555", height=1).pack(fill=tk.X, pady=8)

        yj_frame = tk.Frame(fortune_panel, bg=frame_bg)
        yj_frame.pack(pady=5, fill=tk.X)

        good_frame = tk.Frame(yj_frame, bg="#E8F8F5" if not self.is_dark_mode else "#1a3a2a", relief=tk.FLAT, bd=1)
        good_frame.pack(fill=tk.X, pady=3)
        tk.Label(good_frame, text="✅ 今日宜", font=("微软雅黑", 10, "bold"),
                 bg="#E8F8F5" if not self.is_dark_mode else "#1a3a2a",
                 fg="#27AE60").pack(anchor="w", padx=8, pady=3)
        for item in good_list:
            tk.Label(good_frame, text=f"  • {item}", font=("微软雅黑", 9),
                     bg="#E8F8F5" if not self.is_dark_mode else "#1a3a2a",
                     fg=self.text_color, anchor="w").pack(fill=tk.X, padx=8, pady=1)

        bad_frame = tk.Frame(yj_frame, bg="#FDEDEC" if not self.is_dark_mode else "#3a1a1a", relief=tk.FLAT, bd=1)
        bad_frame.pack(fill=tk.X, pady=3)
        tk.Label(bad_frame, text="❌ 今日忌", font=("微软雅黑", 10, "bold"),
                 bg="#FDEDEC" if not self.is_dark_mode else "#3a1a1a",
                 fg="#E74C3C").pack(anchor="w", padx=8, pady=3)
        for item in bad_list:
            tk.Label(bad_frame, text=f"  • {item}", font=("微软雅黑", 9),
                     bg="#FDEDEC" if not self.is_dark_mode else "#3a1a1a",
                     fg=self.text_color, anchor="w").pack(fill=tk.X, padx=8, pady=1)

        tk.Frame(fortune_panel, bg="#E0E0E0" if not self.is_dark_mode else "#555", height=1).pack(fill=tk.X, pady=8)

        tk.Label(fortune_panel, text=f"💡 {daily_tip}", font=("微软雅黑", 9, "bold"),
                 bg=frame_bg, fg=self.primary_color, wraplength=260, justify="center").pack(pady=(5, 3))

        tk.Label(fortune_panel, text=f"💝 {warm_word}", font=("微软雅黑", 9),
                 bg=frame_bg, fg="#7F8C8D", wraplength=260, justify="center").pack(pady=(0, 5))

        return frame

    def preload_page_hash(self, parent):
        """预加载文件哈希校验页"""
        frame = tk.Frame(parent, bg=self.bg_color)

        tk.Label(frame, text="🔐 文件哈希校验器", font=("微软雅黑", 22, "bold"),
                 bg=self.bg_color, fg=self.primary_color).pack(pady=(10, 20), anchor="w")

        file_frame = tk.Frame(frame, bg="white" if not self.is_dark_mode else "#2d2d2d", bd=2,
                              relief=tk.RIDGE)
        file_frame.pack(fill=tk.X, padx=0, pady=10)

        inner = tk.Frame(file_frame, bg="white" if not self.is_dark_mode else "#2d2d2d")
        inner.pack(padx=20, pady=15, fill=tk.X)

        frame_bg = "white" if not self.is_dark_mode else "#2d2d2d"

        self.file_path = tk.StringVar()
        tk.Label(inner, text="选择文件：", bg=frame_bg, font=("微软雅黑", 12), fg=self.text_color).grid(row=0, column=0,
                                                                                                       sticky="w",
                                                                                                       padx=5)
        tk.Entry(inner, textvariable=self.file_path, font=("微软雅黑", 12), width=50).grid(row=0, column=1, padx=5)

        def select_file():
            path = filedialog.askopenfilename(title="选择文件")
            if path:
                self.file_path.set(path)
                self.calculate_hash()

        tk.Button(inner, text="浏览", command=select_file, bg=self.button_bg, fg="white",
                  font=("微软雅黑", 10)).grid(row=0, column=2, padx=5)

        result_frame = tk.Frame(frame, bg=frame_bg, bd=2, relief=tk.RIDGE)
        result_frame.pack(fill=tk.BOTH, expand=True, pady=10)

        result_inner = tk.Frame(result_frame, bg=frame_bg)
        result_inner.pack(padx=20, pady=15, fill=tk.BOTH, expand=True)

        tk.Label(result_inner, text="MD5：", font=("微软雅黑", 11, "bold"),
                 bg=frame_bg, fg=self.text_color).grid(row=0, column=0, sticky="w", pady=5)
        self.md5_result = tk.Entry(result_inner, font=("微软雅黑", 10), width=60)
        self.md5_result.grid(row=0, column=1, padx=5, pady=5)

        tk.Label(result_inner, text="SHA1：", font=("微软雅黑", 11, "bold"),
                 bg=frame_bg, fg=self.text_color).grid(row=1, column=0, sticky="w", pady=5)
        self.sha1_result = tk.Entry(result_inner, font=("微软雅黑", 10), width=60)
        self.sha1_result.grid(row=1, column=1, padx=5, pady=5)

        tk.Label(result_inner, text="SHA256：", font=("微软雅黑", 11, "bold"),
                 bg=frame_bg, fg=self.text_color).grid(row=2, column=0, sticky="w", pady=5)
        self.sha256_result = tk.Entry(result_inner, font=("微软雅黑", 10), width=60)
        self.sha256_result.grid(row=2, column=1, padx=5, pady=5)

        compare_frame = tk.Frame(frame, bg=frame_bg, bd=2, relief=tk.RIDGE)
        compare_frame.pack(fill=tk.X, pady=10)

        compare_inner = tk.Frame(compare_frame, bg=frame_bg)
        compare_inner.pack(padx=20, pady=15, fill=tk.X)

        tk.Label(compare_inner, text="对比哈希值：", bg=frame_bg, font=("微软雅黑", 12), fg=self.text_color).grid(row=0,
                                                                                                                 column=0,
                                                                                                                 sticky="w",
                                                                                                                 padx=5)
        self.compare_hash = tk.Entry(compare_inner, font=("微软雅黑", 12), width=40)
        self.compare_hash.grid(row=0, column=1, padx=5)

        def verify_hash():
            target = self.compare_hash.get().strip().lower()
            if not target:
                messagebox.showwarning("提示", "请输入要对比的哈希值")
                return
            md5_val = self.md5_result.get().strip().lower()
            sha1_val = self.sha1_result.get().strip().lower()
            sha256_val = self.sha256_result.get().strip().lower()

            if target == md5_val:
                messagebox.showinfo("验证结果", "✅ MD5 匹配成功！")
            elif target == sha1_val:
                messagebox.showinfo("验证结果", "✅ SHA1 匹配成功！")
            elif target == sha256_val:
                messagebox.showinfo("验证结果", "✅ SHA256 匹配成功！")
            else:
                messagebox.showwarning("验证结果", "❌ 哈希值不匹配！")

        tk.Button(compare_inner, text="验证", command=verify_hash, bg=self.button_bg,
                  fg="white", font=("微软雅黑", 10)).grid(row=0, column=2, padx=5)

        return frame

    def calculate_hash(self):
        path = self.file_path.get()
        if not os.path.exists(path):
            return

        def calc():
            try:
                md5 = hashlib.md5()
                sha1 = hashlib.sha1()
                sha256 = hashlib.sha256()

                with open(path, 'rb') as f:
                    while chunk := f.read(8192):
                        md5.update(chunk)
                        sha1.update(chunk)
                        sha256.update(chunk)

                self.root.after(0, lambda: self.md5_result.delete(0, tk.END))
                self.root.after(0, lambda: self.md5_result.insert(0, md5.hexdigest()))
                self.root.after(0, lambda: self.sha1_result.delete(0, tk.END))
                self.root.after(0, lambda: self.sha1_result.insert(0, sha1.hexdigest()))
                self.root.after(0, lambda: self.sha256_result.delete(0, tk.END))
                self.root.after(0, lambda: self.sha256_result.insert(0, sha256.hexdigest()))

                numbered_print(f"[{get_time_str()}] 文件哈希计算完成: {os.path.basename(path)}")
            except Exception as e:
                self.root.after(0, lambda: messagebox.showerror("错误", f"计算失败：{str(e)}"))

        threading.Thread(target=calc, daemon=True).start()

    def preload_page_pomodoro(self, parent):
        """预加载番茄钟页"""
        frame = tk.Frame(parent, bg=self.bg_color)

        tk.Label(frame, text="🍅 番茄钟定时器", font=("微软雅黑", 22, "bold"),
                 bg=self.bg_color, fg=self.primary_color).pack(pady=(10, 20), anchor="w")

        setting_frame = tk.Frame(frame, bg="white" if not self.is_dark_mode else "#2d2d2d", bd=2,
                                 relief=tk.RIDGE)
        setting_frame.pack(fill=tk.X, padx=0, pady=10)

        setting_inner = tk.Frame(setting_frame, bg="white" if not self.is_dark_mode else "#2d2d2d")
        setting_inner.pack(padx=20, pady=15)

        frame_bg = "white" if not self.is_dark_mode else "#2d2d2d"

        tk.Label(setting_inner, text="工作时长(分钟)：", bg=frame_bg,
                 font=("微软雅黑", 12), fg=self.text_color).grid(row=0, column=0, padx=5, pady=5)
        self.work_minutes = tk.Entry(setting_inner, font=("微软雅黑", 12), width=8)
        self.work_minutes.grid(row=0, column=1, padx=5, pady=5)
        self.work_minutes.insert(0, "25")

        tk.Label(setting_inner, text="休息时长(分钟)：", bg=frame_bg,
                 font=("微软雅黑", 12), fg=self.text_color).grid(row=0, column=2, padx=5, pady=5)
        self.break_minutes = tk.Entry(setting_inner, font=("微软雅黑", 12), width=8)
        self.break_minutes.grid(row=0, column=3, padx=5, pady=5)
        self.break_minutes.insert(0, "5")

        self.timer_display = tk.Label(frame, text="25:00", font=("微软雅黑", 72, "bold"),
                                      bg=self.bg_color, fg=self.primary_color)
        self.timer_display.pack(pady=30)

        self.progress_bar = ttk.Progressbar(frame, length=400, mode='determinate')
        self.progress_bar.pack(pady=10)

        self.pomodoro_status_label = tk.Label(frame, text="⏸ 未开始", font=("微软雅黑", 14),
                                              bg=self.bg_color, fg=self.text_color)
        self.pomodoro_status_label.pack(pady=5)

        btn_frame = tk.Frame(frame, bg=self.bg_color)
        btn_frame.pack(pady=20)

        tk.Button(btn_frame, text="▶ 开始", font=("微软雅黑", 12, "bold"),
                  bg="#1F7A48", fg="white", relief=tk.FLAT, padx=18, pady=6,
                  command=self.start_pomodoro).grid(row=0, column=0, padx=8)

        tk.Button(btn_frame, text="⏸ 暂停", font=("微软雅黑", 12, "bold"),
                  bg="#F59E0B", fg="white", relief=tk.FLAT, padx=18, pady=6,
                  command=self.pause_pomodoro).grid(row=0, column=1, padx=8)

        tk.Button(btn_frame, text="⏹ 重置", font=("微软雅黑", 12, "bold"),
                  bg="#dc2626", fg="white", relief=tk.FLAT, padx=18, pady=6,
                  command=self.reset_pomodoro).grid(row=0, column=2, padx=8)

        return frame

    def start_pomodoro(self):
        if self.pomodoro_running:
            return
        try:
            work_min = int(self.work_minutes.get())
            break_min = int(self.break_minutes.get())
            if work_min <= 0 or break_min <= 0:
                raise ValueError
            self.pomodoro_work_time = work_min * 60
            self.pomodoro_break_time = break_min * 60
        except:
            messagebox.showwarning("提示", "请输入有效的工作/休息时长")
            return

        self.pomodoro_running = True
        self.pomodoro_type = "work"
        self.pomodoro_remaining = self.pomodoro_work_time
        self.update_timer_display()
        self.run_pomodoro_timer()

    def run_pomodoro_timer(self):
        if not self.pomodoro_running:
            return

        if self.pomodoro_remaining <= 0:
            if self.pomodoro_type == "work":
                self.pomodoro_type = "break"
                self.pomodoro_remaining = self.pomodoro_break_time
                self.pomodoro_status_label.config(text="☕ 休息时间", fg="#F59E0B")
                self.root.bell()
                messagebox.showinfo("番茄钟", "工作完成！休息一下吧~")
            else:
                self.pomodoro_type = "work"
                self.pomodoro_remaining = self.pomodoro_work_time
                self.pomodoro_status_label.config(text="📚 工作时间", fg=self.primary_color)
                self.root.bell()
                messagebox.showinfo("番茄钟", "休息结束！继续工作吧~")

        if self.pomodoro_type == "work":
            total = self.pomodoro_work_time
            self.progress_bar['maximum'] = total
            self.progress_bar['value'] = total - self.pomodoro_remaining
            self.pomodoro_status_label.config(text="📚 工作时间", fg=self.primary_color)
        else:
            total = self.pomodoro_break_time
            self.progress_bar['maximum'] = total
            self.progress_bar['value'] = total - self.pomodoro_remaining
            self.pomodoro_status_label.config(text="☕ 休息时间", fg="#F59E0B")

        minutes = self.pomodoro_remaining // 60
        seconds = self.pomodoro_remaining % 60
        self.timer_display.config(text=f"{minutes:02d}:{seconds:02d}")

        self.pomodoro_remaining -= 1
        self.pomodoro_thread = self.root.after(1000, self.run_pomodoro_timer)

    def pause_pomodoro(self):
        if self.pomodoro_thread:
            self.root.after_cancel(self.pomodoro_thread)
            self.pomodoro_thread = None
        self.pomodoro_running = False
        self.pomodoro_status_label.config(text="⏸ 已暂停", fg=self.text_color)

    def reset_pomodoro(self):
        self.pause_pomodoro()
        self.pomodoro_type = "work"
        self.pomodoro_remaining = self.pomodoro_work_time if hasattr(self, 'pomodoro_work_time') else 25 * 60
        self.update_timer_display()
        self.progress_bar['value'] = 0
        self.pomodoro_status_label.config(text="⏸ 未开始", fg=self.text_color)

    def update_timer_display(self):
        minutes = self.pomodoro_remaining // 60
        seconds = self.pomodoro_remaining % 60
        self.timer_display.config(text=f"{minutes:02d}:{seconds:02d}")

    def preload_page_qrcode(self, parent):
        """预加载二维码生成器页"""
        frame = tk.Frame(parent, bg=self.bg_color)

        tk.Label(frame, text="📱 二维码生成器", font=("微软雅黑", 22, "bold"),
                 bg=self.bg_color, fg=self.primary_color).pack(pady=(10, 20), anchor="w")

        main_content = tk.Frame(frame, bg=self.bg_color)
        main_content.pack(fill=tk.BOTH, expand=True)

        left_panel = tk.Frame(main_content, bg=self.bg_color)
        left_panel.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 10))

        input_frame = tk.Frame(left_panel, bg="white" if not self.is_dark_mode else "#2d2d2d", bd=2, relief=tk.RIDGE)
        input_frame.pack(fill=tk.X, pady=(0, 10))

        input_inner = tk.Frame(input_frame, bg="white" if not self.is_dark_mode else "#2d2d2d")
        input_inner.pack(padx=20, pady=15, fill=tk.X)

        label_bg = "white" if not self.is_dark_mode else "#2d2d2d"
        label_fg = self.text_color

        tk.Label(input_inner, text="文本/链接：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).grid(row=0, column=0,
                                                                                                       sticky="w",
                                                                                                       padx=5, pady=5)
        self.qr_text = tk.Entry(input_inner, font=("微软雅黑", 12), width=40)
        self.qr_text.grid(row=0, column=1, padx=5, pady=5, columnspan=2)
        self.qr_text.insert(0, "https://space.bilibili.com/3493288684292639")

        tk.Label(input_inner, text="二维码尺寸：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).grid(row=1, column=0,
                                                                                                        sticky="w",
                                                                                                        padx=5, pady=5)
        self.qr_size = tk.StringVar(value="300")
        size_combo = ttk.Combobox(input_inner, textvariable=self.qr_size,
                                  values=["200", "250", "300", "400", "500", "600", "800", "1000", "2000", "5000",
                                          "10000"],
                                  state="readonly", width=8)
        size_combo.grid(row=1, column=1, sticky="w", padx=5, pady=5)

        tk.Label(input_inner, text="预留边框：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).grid(row=2, column=0,
                                                                                                      sticky="w",
                                                                                                      padx=5, pady=5)
        self.qr_border = tk.BooleanVar(value=True)
        border_check = tk.Checkbutton(input_inner, text="预留边框",
                                      variable=self.qr_border, bg=label_bg, font=("微软雅黑", 10))
        border_check.grid(row=2, column=1, columnspan=2, sticky="w", padx=5, pady=5)

        tk.Label(input_inner, text="方块样式：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).grid(row=3, column=0,
                                                                                                      sticky="w",
                                                                                                      padx=5, pady=5)
        self.qr_style = tk.StringVar(value="圆角方块")
        style_combo = ttk.Combobox(input_inner, textvariable=self.qr_style,
                                   values=["直角方块", "圆角方块", "圆形点"],
                                   state="readonly", width=10)
        style_combo.grid(row=3, column=1, sticky="w", padx=5, pady=5)

        self.radius_frame = tk.Frame(input_inner, bg=label_bg)
        self.radius_frame.grid(row=4, column=0, columnspan=3, sticky="ew", padx=5, pady=5)
        self.radius_frame.grid_remove()

        tk.Label(self.radius_frame, text="圆角半径：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).grid(row=0,
                                                                                                            column=0,
                                                                                                            sticky="w",
                                                                                                            padx=5)
        self.qr_radius = tk.StringVar(value="30")
        radius_scale = tk.Scale(self.radius_frame, from_=0, to=50, orient=tk.HORIZONTAL,
                                variable=self.qr_radius, bg=label_bg, length=150)
        radius_scale.grid(row=0, column=1, sticky="w", padx=5)
        self.radius_label = tk.Label(self.radius_frame, text="30%", bg=label_bg, font=("微软雅黑", 10), fg=label_fg)
        self.radius_label.grid(row=0, column=2, sticky="w", padx=5)

        def update_radius_label(*args):
            self.radius_label.config(text=f"{self.qr_radius.get()}%")

        self.qr_radius.trace_add('write', lambda *args: update_radius_label())

        def toggle_radius_visibility(*args):
            if self.qr_style.get() == "圆角方块":
                self.radius_frame.grid()
            else:
                self.radius_frame.grid_remove()

        self.qr_style.trace_add('write', toggle_radius_visibility)
        toggle_radius_visibility()

        color_frame = tk.Frame(input_inner, bg=label_bg)
        color_frame.grid(row=5, column=0, columnspan=3, pady=10, sticky="ew")

        tk.Label(color_frame, text="前景色：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).pack(side=tk.LEFT,
                                                                                                    padx=5)
        self.qr_fg_btn = tk.Button(color_frame, text="选择颜色", command=self.choose_qr_fg_color,
                                   bg="#000000", fg="white", font=("微软雅黑", 10), width=8)
        self.qr_fg_btn.pack(side=tk.LEFT, padx=5)
        self.qr_fg_color = "#000000"

        tk.Label(color_frame, text="背景色：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).pack(side=tk.LEFT,
                                                                                                    padx=5)
        self.qr_bg_btn = tk.Button(color_frame, text="选择颜色", command=self.choose_qr_bg_color,
                                   bg="#FFFFFF", fg="black", font=("微软雅黑", 10), width=8)
        self.qr_bg_btn.pack(side=tk.LEFT, padx=5)
        self.qr_bg_color = "#FFFFFF"

        tk.Label(input_inner, text="方块间距：", bg=label_bg, font=("微软雅黑", 12), fg=label_fg).grid(row=6, column=0,
                                                                                                      sticky="w",
                                                                                                      padx=5, pady=5)
        self.qr_spacing = tk.StringVar(value="0")
        spacing_scale = tk.Scale(input_inner, from_=0, to=10, orient=tk.HORIZONTAL,
                                 variable=self.qr_spacing, bg=label_bg, length=150)
        spacing_scale.grid(row=6, column=1, sticky="w", padx=5, pady=5)
        spacing_label = tk.Label(input_inner, text="0px", bg=label_bg, font=("微软雅黑", 10), fg=label_fg)
        spacing_label.grid(row=6, column=2, sticky="w", padx=5)

        def update_spacing_label(*args):
            spacing_label.config(text=f"{self.qr_spacing.get()}px")

        self.qr_spacing.trace_add('write', lambda *args: update_spacing_label())

        btn_frame = tk.Frame(left_panel, bg=self.bg_color)
        btn_frame.pack(fill=tk.X, pady=10)

        def generate_qr():
            text = self.qr_text.get().strip()
            if not text:
                messagebox.showwarning("提示", "请输入文本或链接")
                return
            try:
                target_size = int(self.qr_size.get())
                radius = int(self.qr_radius.get())
                spacing = int(self.qr_spacing.get())
                style = self.qr_style.get()
                has_border = self.qr_border.get()

                import qrcode
                from PIL import Image, ImageDraw

                qr = qrcode.QRCode(
                    version=None,
                    error_correction=qrcode.constants.ERROR_CORRECT_H,
                    box_size=10,
                    border=2,
                )
                qr.add_data(text)
                qr.make(fit=True)

                qr_matrix = qr.get_matrix()
                matrix_size = len(qr_matrix)

                total_spacing = spacing * (matrix_size - 1)

                if has_border:
                    available_size = target_size - 40
                    module_size = (available_size - total_spacing) // matrix_size
                    if module_size < 1:
                        module_size = 1
                    actual_content_size = module_size * matrix_size + total_spacing
                    canvas_size = target_size
                    start_x = (canvas_size - actual_content_size) // 2
                    start_y = (canvas_size - actual_content_size) // 2
                else:
                    module_size = (target_size - total_spacing) // matrix_size
                    if module_size < 1:
                        module_size = 1
                    actual_content_size = module_size * matrix_size + total_spacing
                    canvas_size = actual_content_size
                    start_x = 0
                    start_y = 0

                img = Image.new("RGB", (canvas_size, canvas_size), self.qr_bg_color)
                draw = ImageDraw.Draw(img)

                for y, row in enumerate(qr_matrix):
                    for x, cell in enumerate(row):
                        if cell:
                            x1 = start_x + x * (module_size + spacing)
                            y1 = start_y + y * (module_size + spacing)
                            x2 = x1 + module_size
                            y2 = y1 + module_size

                            if style == "直角方块":
                                draw.rectangle([x1, y1, x2, y2], fill=self.qr_fg_color)
                            elif style == "圆角方块":
                                corner_radius = int(module_size * radius / 100)
                                draw.rounded_rectangle([x1, y1, x2, y2],
                                                       radius=corner_radius,
                                                       fill=self.qr_fg_color)
                            elif style == "圆形点":
                                center_x = (x1 + x2) // 2
                                center_y = (y1 + y2) // 2
                                circle_radius = module_size // 2
                                if spacing == 0:
                                    circle_radius = int(circle_radius * 0.8)
                                draw.ellipse([center_x - circle_radius, center_y - circle_radius,
                                              center_x + circle_radius, center_y + circle_radius],
                                             fill=self.qr_fg_color)

                self.qr_image = ImageTk.PhotoImage(img)
                self.qr_label.config(image=self.qr_image)
                numbered_print(f"[{get_time_str()}] 二维码生成成功")
            except Exception as e:
                messagebox.showerror("错误", f"生成失败：{str(e)}")

        generate_btn = tk.Button(btn_frame, text="🎨 生成二维码", command=generate_qr,
                                 bg=self.button_bg, fg="white",
                                 font=("微软雅黑", 12, "bold"), padx=15, pady=6)
        generate_btn.pack(side=tk.LEFT, expand=True, fill=tk.X, padx=5)

        def save_qr():
            if hasattr(self, 'qr_image') and self.qr_image:
                file_path = filedialog.asksaveasfilename(defaultextension=".png",
                                                         filetypes=[("PNG文件", "*.png"), ("所有文件", "*.*")])
                if file_path:
                    try:
                        text = self.qr_text.get().strip()
                        target_size = int(self.qr_size.get())
                        radius = int(self.qr_radius.get())
                        spacing = int(self.qr_spacing.get())
                        style = self.qr_style.get()
                        has_border = self.qr_border.get()

                        import qrcode
                        from PIL import Image, ImageDraw

                        qr = qrcode.QRCode(
                            version=None,
                            error_correction=qrcode.constants.ERROR_CORRECT_H,
                            box_size=10,
                            border=2,
                        )
                        qr.add_data(text)
                        qr.make(fit=True)

                        qr_matrix = qr.get_matrix()
                        matrix_size = len(qr_matrix)

                        total_spacing = spacing * (matrix_size - 1)

                        if has_border:
                            available_size = target_size - 40
                            module_size = (available_size - total_spacing) // matrix_size
                            if module_size < 1:
                                module_size = 1
                            actual_content_size = module_size * matrix_size + total_spacing
                            canvas_size = target_size
                            start_x = (canvas_size - actual_content_size) // 2
                            start_y = (canvas_size - actual_content_size) // 2
                        else:
                            module_size = (target_size - total_spacing) // matrix_size
                            if module_size < 1:
                                module_size = 1
                            actual_content_size = module_size * matrix_size + total_spacing
                            canvas_size = actual_content_size
                            start_x = 0
                            start_y = 0

                        img = Image.new("RGB", (canvas_size, canvas_size), self.qr_bg_color)
                        draw = ImageDraw.Draw(img)

                        for y, row in enumerate(qr_matrix):
                            for x, cell in enumerate(row):
                                if cell:
                                    x1 = start_x + x * (module_size + spacing)
                                    y1 = start_y + y * (module_size + spacing)
                                    x2 = x1 + module_size
                                    y2 = y1 + module_size

                                    if style == "直角方块":
                                        draw.rectangle([x1, y1, x2, y2], fill=self.qr_fg_color)
                                    elif style == "圆角方块":
                                        corner_radius = int(module_size * radius / 100)
                                        draw.rounded_rectangle([x1, y1, x2, y2],
                                                               radius=corner_radius,
                                                               fill=self.qr_fg_color)
                                    elif style == "圆形点":
                                        center_x = (x1 + x2) // 2
                                        center_y = (y1 + y2) // 2
                                        circle_radius = module_size // 2
                                        if spacing == 0:
                                            circle_radius = int(circle_radius * 0.8)
                                        draw.ellipse([center_x - circle_radius, center_y - circle_radius,
                                                      center_x + circle_radius, center_y + circle_radius],
                                                     fill=self.qr_fg_color)

                        img.save(file_path)
                        messagebox.showinfo("成功", f"二维码已保存到：{file_path}")
                    except Exception as e:
                        messagebox.showerror("错误", f"保存失败：{str(e)}")

        save_btn = tk.Button(btn_frame, text="💾 保存二维码", command=save_qr,
                             bg=self.button_bg, fg="white", font=("微软雅黑", 12, "bold"),
                             padx=15, pady=6)
        save_btn.pack(side=tk.RIGHT, expand=True, fill=tk.X, padx=5)

        right_panel = tk.Frame(main_content, bg="white" if not self.is_dark_mode else "#2d2d2d",
                               bd=2, relief=tk.RIDGE, width=450)
        right_panel.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
        right_panel.pack_propagate(False)

        display_inner = tk.Frame(right_panel, bg="white" if not self.is_dark_mode else "#2d2d2d")
        display_inner.pack(expand=True, fill=tk.BOTH)

        self.qr_label = tk.Label(display_inner, bg="white" if not self.is_dark_mode else "#2d2d2d")
        self.qr_label.pack(expand=True)

        self.root.after(100, generate_qr)

        return frame

    def choose_qr_fg_color(self):
        color = colorchooser.askcolor(title="选择二维码颜色", initialcolor=self.qr_fg_color)[1]
        if color:
            self.qr_fg_color = color
            self.qr_fg_btn.config(bg=color)
            if sum(int(color[i:i + 2], 16) for i in (1, 3, 5)) / 3 < 128:
                self.qr_fg_btn.config(fg="white")
            else:
                self.qr_fg_btn.config(fg="black")

    def choose_qr_bg_color(self):
        color = colorchooser.askcolor(title="选择背景颜色", initialcolor=self.qr_bg_color)[1]
        if color:
            self.qr_bg_color = color
            self.qr_bg_btn.config(bg=color)
            if sum(int(color[i:i + 2], 16) for i in (1, 3, 5)) / 3 < 128:
                self.qr_bg_btn.config(fg="white")
            else:
                self.qr_bg_btn.config(fg="black")

    def preload_page_translate(self, parent):
        """预加载多语言翻译页"""
        frame = tk.Frame(parent, bg=self.bg_color)

        self.languages = {
            "中文(简体)": "zh", "中文(繁体)": "zh-TW", "粤语": "yue",
            "英语": "en", "日语": "ja", "韩语": "ko", "俄语": "ru",
            "法语": "fr", "德语": "de", "西班牙语": "es", "意大利语": "it",
            "葡萄牙语": "pt", "阿拉伯语": "ar", "荷兰语": "nl", "波兰语": "pl",
            "土耳其语": "tr", "泰语": "th", "越南语": "vi", "希腊语": "el",
            "希伯来语": "he", "瑞典语": "sv", "丹麦语": "da", "芬兰语": "fi",
            "挪威语": "no", "捷克语": "cs", "匈牙利语": "hu", "罗马尼亚语": "ro",
            "乌克兰语": "uk", "印地语": "hi", "印尼语": "id", "马来语": "ms", "拉丁语": "la"
        }

        main_canvas = tk.Canvas(frame, bg=self.bg_color, highlightthickness=0)
        scrollbar = tk.Scrollbar(frame, orient=tk.VERTICAL, command=main_canvas.yview)
        scrollable_frame = tk.Frame(main_canvas, bg=self.bg_color)

        scrollable_frame.bind("<Configure>", lambda e: main_canvas.configure(scrollregion=main_canvas.bbox("all")))
        main_canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
        main_canvas.configure(yscrollcommand=scrollbar.set)

        def on_canvas_configure(event):
            main_canvas.itemconfig("all", width=event.width)

        main_canvas.bind("<Configure>", on_canvas_configure)

        main_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        main_container = scrollable_frame

        tk.Label(main_container, text="🌐 多语言翻译器", font=("微软雅黑", 22, "bold"),
                 bg=self.bg_color, fg=self.primary_color).pack(pady=(10, 15), anchor="w", padx=10)

        panels_frame = tk.Frame(main_container, bg=self.bg_color)
        panels_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)

        left_panel = tk.Frame(panels_frame, bg="white" if not self.is_dark_mode else "#2d2d2d", bd=2, relief=tk.RIDGE)
        left_panel.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 10))

        left_title = tk.Frame(left_panel, bg="white" if not self.is_dark_mode else "#2d2d2d")
        left_title.pack(fill=tk.X, padx=12, pady=(10, 6))
        tk.Label(left_title, text="📝 输入文本", font=("微软雅黑", 13, "bold"),
                 bg="white" if not self.is_dark_mode else "#2d2d2d", fg=self.primary_color).pack(side=tk.LEFT)

        source_frame = tk.Frame(left_panel, bg="white" if not self.is_dark_mode else "#2d2d2d")
        source_frame.pack(fill=tk.X, padx=12, pady=(0, 8))

        tk.Label(source_frame, text="源语言：", font=("微软雅黑", 9),
                 bg="white" if not self.is_dark_mode else "#2d2d2d", fg=self.text_color).pack(side=tk.LEFT)

        self.source_lang = tk.StringVar(value="中文(简体)")
        source_combo = ttk.Combobox(source_frame, textvariable=self.source_lang,
                                    values=list(self.languages.keys()),
                                    state="readonly", width=14, font=("微软雅黑", 9))
        source_combo.pack(side=tk.LEFT, padx=5)

        self.auto_detect = tk.BooleanVar(value=True)
        auto_check = tk.Checkbutton(source_frame, text="自动", variable=self.auto_detect,
                                    bg="white" if not self.is_dark_mode else "#2d2d2d", font=("微软雅黑", 9))
        auto_check.pack(side=tk.LEFT, padx=5)

        def swap_languages():
            target = self.target_lang.get()
            source = self.source_lang.get()
            self.source_lang.set(target)
            self.target_lang.set(source)
            self.translate_status.config(text="🔄 已交换", fg="#3498db")
            self.root.after(1000, lambda: self.translate_status.config(text="✅ 就绪", fg="#999"))
            self.translate_text()

        swap_btn = tk.Button(source_frame, text="⇄", font=("微软雅黑", 9, "bold"),
                             command=swap_languages, bg=self.button_bg, fg="white",
                             relief=tk.FLAT, width=3)
        swap_btn.pack(side=tk.LEFT, padx=5)

        def clear_input():
            self.input_text.delete("1.0", tk.END)
            self.output_text.config(state=tk.NORMAL)
            self.output_text.delete("1.0", tk.END)
            self.output_text.config(state=tk.DISABLED)
            self.translate_status.config(text="🗑 已清空", fg="#888")
            self.root.after(1500, lambda: self.translate_status.config(text="✅ 就绪", fg="#999"))

        clear_btn = tk.Button(source_frame, text="清空", command=clear_input,
                              bg="#dc2626", fg="white", font=("微软雅黑", 9),
                              relief=tk.FLAT, width=4)
        clear_btn.pack(side=tk.RIGHT, padx=3)

        self.input_text = scrolledtext.ScrolledText(left_panel, font=("微软雅黑", 11),
                                                    wrap=tk.WORD,
                                                    bg="#f8f8f8" if not self.is_dark_mode else "#1e1e1e",
                                                    fg=self.text_color,
                                                    insertbackground=self.text_color,
                                                    height=16)
        self.input_text.pack(fill=tk.BOTH, expand=True, padx=12, pady=(0, 6))
        self.input_text.insert("1.0", "请输入要翻译的文本...")

        char_frame = tk.Frame(left_panel, bg="white" if not self.is_dark_mode else "#2d2d2d")
        char_frame.pack(fill=tk.X, padx=12, pady=(0, 10))
        self.char_count_label = tk.Label(char_frame, text="0 字符", font=("微软雅黑", 8),
                                         bg="white" if not self.is_dark_mode else "#2d2d2d", fg="#999")
        self.char_count_label.pack(side=tk.RIGHT)

        right_panel = tk.Frame(panels_frame, bg="white" if not self.is_dark_mode else "#2d2d2d", bd=2, relief=tk.RIDGE)
        right_panel.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)

        right_title = tk.Frame(right_panel, bg="white" if not self.is_dark_mode else "#2d2d2d")
        right_title.pack(fill=tk.X, padx=12, pady=(10, 6))
        tk.Label(right_title, text="🌍 翻译结果", font=("微软雅黑", 13, "bold"),
                 bg="white" if not self.is_dark_mode else "#2d2d2d", fg=self.primary_color).pack(side=tk.LEFT)

        target_frame = tk.Frame(right_panel, bg="white" if not self.is_dark_mode else "#2d2d2d")
        target_frame.pack(fill=tk.X, padx=12, pady=(0, 8))

        tk.Label(target_frame, text="目标语言：", font=("微软雅黑", 9),
                 bg="white" if not self.is_dark_mode else "#2d2d2d", fg=self.text_color).pack(side=tk.LEFT)

        self.target_lang = tk.StringVar(value="英语")
        target_combo = ttk.Combobox(target_frame, textvariable=self.target_lang,
                                    values=list(self.languages.keys()),
                                    state="readonly", width=14, font=("微软雅黑", 9))
        target_combo.pack(side=tk.LEFT, padx=5)
        target_combo.bind("<<ComboboxSelected>>", lambda e: self.translate_text())

        btn_container = tk.Frame(target_frame, bg="white" if not self.is_dark_mode else "#2d2d2d")
        btn_container.pack(side=tk.RIGHT)

        def copy_result():
            result = self.output_text.get("1.0", tk.END).strip()
            if result:
                self.root.clipboard_clear()
                self.root.clipboard_append(result)
                copy_btn.config(text="✓", bg="#27AE60", width=3)
                self.translate_status.config(text="📋 已复制", fg="#27AE60")
                self.root.after(1500, lambda: copy_btn.config(text="📋", bg=self.button_bg, width=3))
                self.root.after(1500, lambda: self.translate_status.config(text="✅ 就绪", fg="#999"))

        copy_btn = tk.Button(btn_container, text="📋", command=copy_result,
                             bg=self.button_bg, fg="white", font=("微软雅黑", 10),
                             relief=tk.FLAT, width=3)
        copy_btn.pack(side=tk.RIGHT, padx=2)

        self.is_speaking = False
        self.current_engine = None

        def speak_text():
            result = self.output_text.get("1.0", tk.END).strip()
            if not result:
                self.translate_status.config(text="⚠️ 无内容", fg="#F59E0B")
                self.root.after(1500, lambda: self.translate_status.config(text="✅ 就绪", fg="#999"))
                return

            if self.is_speaking and self.current_engine:
                try:
                    self.current_engine.stop()
                    self.current_engine = None
                except:
                    pass
                self.is_speaking = False
                speak_btn.config(text="🔊", bg="#F59E0B")
                self.translate_status.config(text="⏸ 已停止", fg="#888")
                self.root.after(1500, lambda: self.translate_status.config(text="✅ 就绪", fg="#999"))
                return

            speak_btn.config(text="⏸", bg="#dc2626")
            self.is_speaking = True
            self.translate_status.config(text="🔊 朗读中...", fg="#F59E0B")

            def speak_in_thread():
                try:
                    import pyttsx3
                    engine = pyttsx3.init()
                    self.current_engine = engine
                    target_lang = self.target_lang.get()
                    voices = engine.getProperty('voices')
                    if '中文' in target_lang or '粤语' in target_lang:
                        for voice in voices:
                            if 'zh' in voice.id.lower():
                                engine.setProperty('voice', voice.id)
                                break
                    elif '英语' in target_lang:
                        for voice in voices:
                            if 'en' in voice.id.lower():
                                engine.setProperty('voice', voice.id)
                                break
                    engine.setProperty('rate', 150)
                    engine.say(result)
                    engine.runAndWait()
                except Exception as e:
                    pass
                finally:
                    self.root.after(0, lambda: setattr(self, 'is_speaking', False))
                    self.root.after(0, lambda: setattr(self, 'current_engine', None))
                    self.root.after(0, lambda: speak_btn.config(text="🔊", bg="#F59E0B"))
                    self.root.after(0, lambda: self.translate_status.config(text="✅ 完成", fg="#27AE60"))
                    self.root.after(2000, lambda: self.translate_status.config(text="✅ 就绪", fg="#999"))

            threading.Thread(target=speak_in_thread, daemon=True).start()

        speak_btn = tk.Button(btn_container, text="🔊", command=speak_text,
                              bg="#F59E0B", fg="white", font=("微软雅黑", 10),
                              relief=tk.FLAT, width=3)
        speak_btn.pack(side=tk.RIGHT, padx=2)

        self.output_text = scrolledtext.ScrolledText(right_panel, font=("微软雅黑", 11),
                                                     wrap=tk.WORD,
                                                     bg="#f8f8f8" if not self.is_dark_mode else "#1e1e1e",
                                                     fg=self.text_color,
                                                     state=tk.DISABLED,
                                                     height=16)
        self.output_text.pack(fill=tk.BOTH, expand=True, padx=12, pady=(0, 10))

        btn_bar = tk.Frame(main_container, bg=self.bg_color)
        btn_bar.pack(fill=tk.X, pady=8, padx=10)

        def translate_text():
            text = self.input_text.get("1.0", tk.END).strip()
            if not text or text == "请输入要翻译的文本...":
                self.translate_status.config(text="⚠️ 请输入文本", fg="#F59E0B")
                self.root.after(1500, lambda: self.translate_status.config(text="✅ 就绪", fg="#999"))
                return
            self.output_text.config(state=tk.NORMAL)
            self.output_text.delete("1.0", tk.END)
            self.output_text.insert("1.0", "翻译中...")
            self.output_text.config(state=tk.DISABLED)
            self.translate_status.config(text="🔄 翻译中...", fg="#3498db")
            threading.Thread(target=self.do_translate, daemon=True).start()

        translate_btn = tk.Button(btn_bar, text="🌐 开始翻译", command=translate_text,
                                  bg=self.button_bg, fg="white", font=("微软雅黑", 10, "bold"),
                                  relief=tk.FLAT, padx=20, pady=5)
        translate_btn.pack(side=tk.LEFT, padx=5)

        tk.Label(btn_bar, text="快速切换：", font=("微软雅黑", 9),
                 bg=self.bg_color, fg=self.text_color).pack(side=tk.LEFT, padx=(10, 5))

        quick_langs = ["英语", "日语", "韩语", "法语", "德语", "俄语"]
        for lang in quick_langs:
            btn = tk.Button(btn_bar, text=lang,
                            command=lambda l=lang: (self.target_lang.set(l), translate_text()),
                            font=("微软雅黑", 8), bg="#E0E0E0", fg="#333",
                            relief=tk.FLAT, padx=8, pady=3)
            btn.pack(side=tk.LEFT, padx=2)

        self.translate_status = tk.Label(main_container, text="✅ 就绪",
                                         font=("微软雅黑", 9),
                                         bg=self.bg_color, fg="#999")
        self.translate_status.pack(pady=(5, 8), padx=10, anchor="w")

        history_frame = tk.LabelFrame(main_container, text="📜 翻译历史",
                                      font=("微软雅黑", 10, "bold"),
                                      fg=self.primary_color, bd=2,
                                      bg=self.bg_color)
        history_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 10), padx=10)

        self.history_text = scrolledtext.ScrolledText(history_frame, font=("微软雅黑", 9),
                                                      height=5, wrap=tk.WORD,
                                                      bg="white" if not self.is_dark_mode else "#2d2d2d",
                                                      fg=self.text_color)
        self.history_text.pack(fill=tk.BOTH, expand=True, padx=10, pady=8)

        history_btn_frame = tk.Frame(history_frame, bg=self.bg_color)
        history_btn_frame.pack(fill=tk.X, padx=10, pady=(0, 8))

        tk.Label(history_btn_frame, text="💡 📋复制 🔊朗读", font=("微软雅黑", 8),
                 bg=self.bg_color, fg="#888").pack(side=tk.LEFT)

        self.translate_history = []

        def update_history_display():
            self.history_text.config(state=tk.NORMAL)
            self.history_text.delete("1.0", tk.END)
            if not self.translate_history:
                self.history_text.insert("1.0", "暂无翻译历史")
            else:
                for entry in self.translate_history[:10]:
                    line = f"[{entry['time']}] {entry['source_lang']}→{entry['target_lang']}\n"
                    line += f"  {entry['source']}\n  ↓\n  {entry['target']}\n\n"
                    self.history_text.insert(tk.END, line)
            self.history_text.config(state=tk.DISABLED)

        self.update_history_display_translate = update_history_display

        def save_to_history(source_text, target_text, source_lang_name, target_lang_name):
            history_entry = {
                "time": datetime.datetime.now().strftime("%H:%M:%S"),
                "source": source_text[:50] + "..." if len(source_text) > 50 else source_text,
                "target": target_text[:50] + "..." if len(target_text) > 50 else target_text,
                "source_lang": source_lang_name,
                "target_lang": target_lang_name
            }
            self.translate_history.insert(0, history_entry)
            if len(self.translate_history) > 15:
                self.translate_history.pop()
            update_history_display()

        def clear_history():
            self.translate_history = []
            update_history_display()
            self.translate_status.config(text="🗑 历史已清空", fg="#888")
            self.root.after(1500, lambda: self.translate_status.config(text="✅ 就绪", fg="#999"))

        clear_history_btn = tk.Button(history_btn_frame, text="清空历史", command=clear_history,
                                      bg="#95A5A6", fg="white", font=("微软雅黑", 8),
                                      relief=tk.FLAT, padx=10, pady=2)
        clear_history_btn.pack(side=tk.RIGHT)

        def on_mousewheel(event):
            x, y = event.x_root, event.y_root
            widget = main_canvas.winfo_containing(x, y)

            if widget == self.input_text or widget == self.output_text:
                return

            parent = widget
            while parent:
                if parent == self.input_text or parent == self.output_text:
                    return
                parent = parent.master

            main_canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")

        main_canvas.bind("<MouseWheel>", on_mousewheel)

        self.auto_translate_timer = None

        def auto_translate():
            if self.auto_translate_timer:
                self.root.after_cancel(self.auto_translate_timer)
            self.auto_translate_timer = self.root.after(800, translate_text)

        def on_input_focus():
            if self.input_text.get("1.0", tk.END).strip() == "请输入要翻译的文本...":
                self.input_text.delete("1.0", tk.END)

        def update_char_count(event=None):
            count = len(self.input_text.get("1.0", tk.END).strip())
            self.char_count_label.config(text=f"{count} 字符")

        def detect_language(text):
            if re.search(r'[\u4e00-\u9fff]', text):
                return "中文(简体)"
            if re.search(r'[\u3040-\u309F\u30A0-\u30FF]', text):
                return "日语"
            if re.search(r'[\uAC00-\uD7AF]', text):
                return "韩语"
            if re.search(r'[\u0400-\u04FF]', text):
                return "俄语"
            return "英语"

        def on_text_change(event=None):
            if self.auto_detect.get():
                text = self.input_text.get("1.0", tk.END).strip()
                if text and text != "请输入要翻译的文本...":
                    detected = detect_language(text)
                    if detected != self.source_lang.get():
                        self.source_lang.set(detected)
            update_char_count(event)
            auto_translate()

        self.input_text.bind("<FocusIn>", lambda e: on_input_focus())
        self.input_text.bind("<KeyRelease>", on_text_change)
        source_combo.bind("<<ComboboxSelected>>", lambda e: translate_text())

        self.translate_text = translate_text
        self.save_to_history = save_to_history

        return frame

    def do_translate(self):
        """执行翻译的线程函数"""
        try:
            text = self.input_text.get("1.0", tk.END).strip()
            if not text or text == "请输入要翻译的文本...":
                return

            source_lang_name = self.source_lang.get()
            target_lang_name = self.target_lang.get()

            source_code = self.languages.get(source_lang_name, "en")
            target_code = self.languages.get(target_lang_name, "en")

            if source_code == target_code:
                self.root.after(0, lambda: self.display_translation(text, source_lang_name, target_lang_name, text))
                return

            translated_text = None

            try:
                if source_code == "zh":
                    source_code = "zh"
                if source_code == "zh-TW":
                    source_code = "zh-TW"
                if source_code == "yue":
                    source_code = "yue"

                if target_code == "zh":
                    target_code = "zh"
                if target_code == "zh-TW":
                    target_code = "zh-TW"
                if target_code == "yue":
                    target_code = "yue"

                url = "https://api.mymemory.translated.net/get"
                params = {
                    "q": text,
                    "langpair": f"{source_code}|{target_code}",
                    "de": "a@b.c"
                }
                numbered_print(f"[{get_time_str()}] 翻译请求: {source_code} -> {target_code}")

                response = requests.get(url, params=params, timeout=10)
                if response.status_code == 200:
                    data = response.json()
                    translated_text = data.get("responseData", {}).get("translatedText", "")
                    if translated_text and translated_text != text:
                        translated_text = translated_text.replace("&#39;", "'").replace("&quot;", '"')
                        import re
                        translated_text = re.sub(r'\[.*?\]', '', translated_text)
                        self.root.after(0, lambda: self.display_translation(translated_text, source_lang_name,
                                                                            target_lang_name, text))
                        return
            except Exception as e:
                numbered_print(f"[{get_time_str()}] MyMemory翻译失败: {e}")

            if not translated_text:
                try:
                    mirrors = [
                        "https://lingva.ml",
                        "https://translate.plausibility.cloud",
                        "https://lingva.lunar.icu"
                    ]
                    for mirror in mirrors:
                        try:
                            src_code = source_code
                            tgt_code = target_code
                            if src_code == "zh":
                                src_code = "zh-CN"
                            if src_code == "zh-TW":
                                src_code = "zh-TW"
                            if src_code == "yue":
                                src_code = "yue"
                            if tgt_code == "zh":
                                tgt_code = "zh-CN"
                            if tgt_code == "zh-TW":
                                tgt_code = "zh-TW"
                            if tgt_code == "yue":
                                tgt_code = "yue"

                            url = f"{mirror}/api/v1/{src_code}/{tgt_code}/{requests.utils.quote(text)}"
                            response = requests.get(url, timeout=8)
                            if response.status_code == 200:
                                data = response.json()
                                translated_text = data.get("translation", "")
                                if translated_text:
                                    break
                        except:
                            continue
                    if translated_text:
                        self.root.after(0, lambda: self.display_translation(translated_text, source_lang_name,
                                                                            target_lang_name, text))
                        return
                except Exception as e:
                    numbered_print(f"[{get_time_str()}] Lingva翻译失败: {e}")

            if not translated_text:
                translated_text = self.simple_dict_translate(text, source_lang_name, target_lang_name)
                self.root.after(0, lambda: self.display_translation(translated_text, source_lang_name, target_lang_name,
                                                                    text))

        except Exception as e:
            numbered_print(f"[{get_time_str()}] 翻译失败: {e}")
            self.root.after(0, lambda: self.display_translation_error(f"翻译失败: {str(e)}"))

    def display_translation(self, translated_text, source_lang_name, target_lang_name, original_text):
        """显示翻译结果"""
        try:
            self.output_text.config(state=tk.NORMAL)
            self.output_text.delete("1.0", tk.END)
            self.output_text.insert("1.0", translated_text)
            self.output_text.config(state=tk.DISABLED)
            self.translate_status.config(text=f"✅ 翻译完成 | {source_lang_name} → {target_lang_name}", fg="#27AE60")
            self.root.after(2000, lambda: self.translate_status.config(text="✅ 就绪", fg="#999"))

            self.save_to_history(original_text, translated_text, source_lang_name, target_lang_name)
            self.update_history_display_translate()
        except:
            pass

    def display_translation_error(self, error_msg):
        """显示翻译错误"""
        try:
            self.output_text.config(state=tk.NORMAL)
            self.output_text.delete("1.0", tk.END)
            self.output_text.insert("1.0", error_msg)
            self.output_text.config(state=tk.DISABLED)
            self.translate_status.config(text="❌ 翻译失败", fg="#E74C3C")
            self.root.after(2000, lambda: self.translate_status.config(text="✅ 就绪", fg="#999"))
        except:
            pass

    def simple_dict_translate(self, text, source_lang, target_lang):
        """简单的字典翻译备用方案"""
        common_words = {
            "hello": {"英语": "hello", "中文(简体)": "你好", "日语": "こんにちは", "韩语": "안녕하세요",
                      "法语": "bonjour", "德语": "hallo", "俄语": "привет"},
            "good": {"英语": "good", "中文(简体)": "好", "日语": "良い", "韩语": "좋은", "法语": "bien",
                     "德语": "gut", "俄语": "хорошо"},
            "world": {"英语": "world", "中文(简体)": "世界", "日语": "世界", "韩语": "세계", "法语": "monde",
                      "德语": "Welt", "俄语": "мир"},
            "thank you": {"英语": "thank you", "中文(简体)": "谢谢", "日语": "ありがとう", "韩语": "감사합니다",
                          "法语": "merci", "德语": "danke", "俄语": "спасибо"}
        }

        lower_text = text.lower().strip()
        if lower_text in common_words:
            if target_lang in common_words[lower_text]:
                return common_words[lower_text][target_lang]

        return f"[简易翻译] {text}\n(提示: 网络翻译服务可能受限，请检查网络连接)"

    def preload_page_support(self, parent):
        """预加载支持根号七页"""
        frame = tk.Frame(parent, bg=self.bg_color)

        tk.Label(frame, text="💖 支持根号七", font=("微软雅黑", 24, "bold"), bg=self.bg_color,
                 fg=self.primary_color).pack(pady=30)
        content_frame = tk.Frame(frame, bg=self.bg_color)
        content_frame.pack(fill=tk.BOTH, expand=True, padx=50)

        card_bg = "white" if not self.is_dark_mode else "#2d2d2d"

        zanshang = tk.Frame(content_frame, bg=card_bg, bd=2, relief=tk.RIDGE)
        zanshang.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=10, pady=10)
        tk.Label(zanshang, text="💰 赞赏码", font=("微软雅黑", 16, "bold"), bg=card_bg,
                 fg=self.primary_color).pack(pady=20)
        try:
            img = Image.open("赞赏码.png").resize((200, 200))
            self.zan_img = ImageTk.PhotoImage(img)
            tk.Label(zanshang, image=self.zan_img, bg=card_bg).pack()
            numbered_print(f"[{get_time_str()}] 图片 \"赞赏码.png\" 加载成功")
        except:
            tk.Label(zanshang, text="未找到图片", font=("微软雅黑", 12), bg=card_bg,
                     fg=self.text_color).pack()
            numbered_print(f"[{get_time_str()}] 图片 \"赞赏码.png\" 加载失败，未找到图片")
        tk.Label(zanshang, text="谢谢老板~", font=("微软雅黑", 14, "bold"), bg=card_bg,
                 fg=self.primary_color).pack(pady=15)

        qun = tk.Frame(content_frame, bg=card_bg, bd=2, relief=tk.RIDGE)
        qun.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=10, pady=10)
        tk.Label(qun, text="👥 交流群", font=("微软雅黑", 16, "bold"), bg=card_bg,
                 fg=self.primary_color).pack(pady=20)
        try:
            img = Image.open("交流群.png").resize((180, 180))
            self.qun_img = ImageTk.PhotoImage(img)
            tk.Label(qun, image=self.qun_img, bg=card_bg).pack()
            numbered_print(f"[{get_time_str()}] 图片 \"交流群.png\" 加载成功")
        except:
            tk.Label(qun, text="未找到图片", font=("微软雅黑", 12), bg=card_bg,
                     fg=self.text_color).pack()
            numbered_print(f"[{get_time_str()}] 图片 \"交流群.png\" 加载失败，未找到图片")
        tk.Label(qun, text="群号：1083170749", font=("微软雅黑", 14, "bold"), bg=card_bg,
                 fg=self.primary_color).pack(pady=15)

        bili = tk.Frame(content_frame, bg=card_bg, bd=2, relief=tk.RIDGE)
        bili.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=10, pady=10)
        tk.Label(bili, text="📺 B站关注", font=("微软雅黑", 16, "bold"), bg=card_bg,
                 fg=self.primary_color).pack(pady=20)
        tk.Label(bili, text="UP主：根号七大玉", font=("微软雅黑", 14), bg=card_bg,
                 fg=self.text_color).pack(pady=10)

        def open_bili():
            webbrowser.open("https://space.bilibili.com/3493288684292639")

        ttk.Button(bili, text="🚀 立即前往关注", command=open_bili, style="Primary.TButton").pack(pady=30)

        return frame

    def preload_page_settings(self, parent):
        """预加载设置页面"""
        frame = tk.Frame(parent, bg=self.bg_color)

        tk.Label(frame, text="⚙️ 软件设置", font=("微软雅黑", 22, "bold"),
                 bg=self.bg_color, fg=self.primary_color).pack(pady=(10, 20), anchor="w")

        frame_bg = self.bg_color
        label_fg = self.text_color

        hotkey_frame = tk.LabelFrame(frame, text="快捷键设置", font=("微软雅黑", 14, "bold"),
                                     fg=self.primary_color, bd=2)
        hotkey_frame.pack(fill=tk.X, pady=10, padx=0)

        hk_row1 = tk.Frame(hotkey_frame, bg=frame_bg)
        hk_row1.pack(fill=tk.X, pady=8, padx=15)
        tk.Label(hk_row1, text="连点器开关：", bg=frame_bg, font=("微软雅黑", 12), fg=label_fg).pack(side=tk.LEFT)
        self.clicker_hk_var = tk.StringVar(value=self.shortcuts.get("clicker_toggle", "F9"))
        clicker_hk_combo = ttk.Combobox(hk_row1, textvariable=self.clicker_hk_var,
                                        values=["F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11",
                                                "F12"],
                                        state="readonly", width=8)
        clicker_hk_combo.pack(side=tk.LEFT, padx=10)
        tk.Label(hk_row1, text="⚠ 该功能暂时无法使用", bg=frame_bg, font=("微软雅黑", 10), fg="#999").pack(side=tk.LEFT,
                                                                                                           padx=5)

        hk_row2 = tk.Frame(hotkey_frame, bg=frame_bg)
        hk_row2.pack(fill=tk.X, pady=8, padx=15)
        tk.Label(hk_row2, text="悬浮字幕开关：", bg=frame_bg, font=("微软雅黑", 12), fg=label_fg).pack(side=tk.LEFT)
        self.float_hk_var = tk.StringVar(value=self.shortcuts.get("float_toggle", "F10"))
        float_hk_combo = ttk.Combobox(hk_row2, textvariable=self.float_hk_var,
                                      values=["F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11",
                                              "F12"],
                                      state="readonly", width=8)
        float_hk_combo.pack(side=tk.LEFT, padx=10)
        tk.Label(hk_row2, text="⚠ 该功能暂时无法使用", bg=frame_bg, font=("微软雅黑", 10), fg="#999").pack(side=tk.LEFT,
                                                                                                           padx=5)

        theme_frame = tk.LabelFrame(frame, text="主题颜色", font=("微软雅黑", 14, "bold"),
                                    fg=self.primary_color, bd=2)
        theme_frame.pack(fill=tk.X, pady=10, padx=0)

        theme_inner = tk.Frame(theme_frame, bg=frame_bg)
        theme_inner.pack(fill=tk.BOTH, expand=True, padx=15, pady=10)

        preset_colors = ["#1F7A48", "#3498db", "#e74c3c", "#9b59b6", "#f39c12", "#1abc9c", "#e67e22", "#2c3e50"]
        color_row = tk.Frame(theme_inner, bg=frame_bg)
        color_row.pack(pady=10)

        def change_theme_color(color):
            from_color = self.primary_color
            self.fade_color(from_color, color, steps=8, delay=15)
            self.refresh_current_page()
            messagebox.showinfo("设置", f"主题颜色已更改")

        for color in preset_colors:
            color_btn = tk.Button(color_row, bg=color, width=4, height=1,
                                  command=lambda c=color: change_theme_color(c),
                                  relief=tk.RAISED, bd=1)
            color_btn.pack(side=tk.LEFT, padx=5)

        color_frame_inner = tk.Frame(theme_inner, bg=frame_bg)
        color_frame_inner.pack(pady=10)

        def custom_color():
            color = colorchooser.askcolor(title="选择主题颜色", initialcolor=self.primary_color)[1]
            if color:
                change_theme_color(color)

        tk.Button(color_frame_inner, text="🎨 自定义颜色", command=custom_color,
                  bg=self.button_bg, fg="white", font=("微软雅黑", 11), padx=20, pady=5).pack()

        dark_frame = tk.LabelFrame(frame, text="深色模式", font=("微软雅黑", 14, "bold"),
                                   fg=self.primary_color, bd=2)
        dark_frame.pack(fill=tk.X, pady=10, padx=0)

        dark_inner = tk.Frame(dark_frame, bg=frame_bg)
        dark_inner.pack(fill=tk.BOTH, expand=True, padx=15, pady=10)

        self.dark_mode_btn = tk.Button(
            dark_inner,
            text="🌙 开启深色模式" if not self.is_dark_mode else "☀️ 关闭深色模式",
            font=("微软雅黑", 12, "bold"),
            bg="#1F7A48" if not self.is_dark_mode else "#f39c12",
            fg="white",
            relief=tk.FLAT,
            padx=20,
            pady=8,
            cursor="hand2",
            command=self.toggle_dark_mode
        )
        tk.Label(dark_inner, text="⚠ 该功能尚未完善，不建议使用", bg=frame_bg, font=("微软雅黑", 10),
                 fg="#999").pack(pady=(5, 0))
        self.dark_mode_btn.pack(pady=5)

        btn_frame = tk.Frame(frame, bg=self.bg_color)
        btn_frame.pack(pady=20)

        def save_settings():
            self.shortcuts["clicker_toggle"] = self.clicker_hk_var.get()
            self.shortcuts["float_toggle"] = self.float_hk_var.get()
            self.reload_hotkeys()
            if hasattr(self, 'clicker_hk_label'):
                self.clicker_hk_label.config(text=f"快捷键：{self.shortcuts['clicker_toggle']} 切换启动/停止")
            if hasattr(self, 'float_hk_label'):
                self.float_hk_label.config(text=f"快捷键：{self.shortcuts['float_toggle']} 切换显示/隐藏")
            messagebox.showinfo("设置", "设置已保存！")

        def reset_settings():
            self.shortcuts["clicker_toggle"] = "F9"
            self.shortcuts["float_toggle"] = "F10"
            self.clicker_hk_var.set("F9")
            self.float_hk_var.set("F10")
            change_theme_color("#1F7A48")
            if self.is_dark_mode:
                self.toggle_dark_mode()
            messagebox.showinfo("设置", "已恢复默认设置")

        tk.Button(btn_frame, text="💾 保存设置", command=save_settings,
                  bg=self.button_bg, fg="white", font=("微软雅黑", 12, "bold"),
                  padx=20, pady=8, relief=tk.FLAT).pack(side=tk.LEFT, padx=10)

        tk.Button(btn_frame, text="🔄 恢复默认", command=reset_settings,
                  bg="#F59E0B", fg="white", font=("微软雅黑", 12, "bold"),
                  padx=20, pady=8, relief=tk.FLAT).pack(side=tk.LEFT, padx=10)

        return frame

    def toggle_dark_mode(self):
        old_bg = self.bg_color
        self.is_dark_mode = not self.is_dark_mode

        if self.is_dark_mode:
            new_bg = "#1e1e1e"
            self.text_color = "#ffffff"
            self.second_color = "#3d3d3d"  # 深色模式选中背景
            self.hover_color = "#4a4a4a"  # 深色模式悬停颜色
            self.dark_mode_btn.config(text="☀️ 关闭深色模式", bg="#f39c12")
            # 侧边栏
            self.nav_frame.configure(bg="#2d2d2d")
            for btn, _, _, _ in self.nav_buttons:
                btn.configure(style="Nav.TButton")
            self.style.configure("Nav.TButton", background="#2d2d2d", foreground="white")
            self.style.configure("Selected.Nav.TButton", background=self.second_color, foreground="white")
            self.style.map("Nav.TButton", background=[('active', self.hover_color), ('pressed', self.hover_color)])
            # 用户信息区域
            self.user_info_label.configure(bg="#2d2d2d", fg="#aaa")
            self.user_avatar_label.configure(bg="#2d2d2d")
            self.name_label.configure(bg="#2d2d2d", fg="white")
            # 底部版本栏
            self.footer_frame.configure(bg="#1a1a1a")
            self.version_label.configure(bg="#1a1a1a", fg="#aaa")
        else:
            new_bg = "#F0F0F0"
            self.text_color = "#333333"
            self.second_color = "#E3F2EB"  # 浅色模式选中背景
            self.hover_color = "#D4E8DC"  # 浅色模式悬停颜色
            self.dark_mode_btn.config(text="🌙 开启深色模式", bg="#1F7A48")
            self.nav_frame.configure(bg="white")
            self.style.configure("Nav.TButton", background="white", foreground=self.text_color)
            self.style.configure("Selected.Nav.TButton", background=self.second_color, foreground=self.text_color)
            self.style.map("Nav.TButton", background=[('active', self.hover_color), ('pressed', self.hover_color)])
            self.user_info_label.configure(bg="white", fg="#666666")
            self.user_avatar_label.configure(bg="white")
            self.name_label.configure(bg="white", fg=self.text_color)
            self.footer_frame.configure(bg="#DCDCDC")
            self.version_label.configure(bg="#DCDCDC", fg="black")

        # 使用渐变切换背景色
        self.fade_bg(old_bg, new_bg, steps=10, delay=15)

        # 刷新所有页面
        self.refresh_current_page()

        messagebox.showinfo("深色模式", "深色模式已" + ("开启" if self.is_dark_mode else "关闭"))

    def reload_hotkeys(self):
        if hasattr(self, 'hotkey_listener') and self.hotkey_listener:
            try:
                self.hotkey_listener.stop()
            except:
                pass
        self.setup_clicker_global_hotkeys()

        if hasattr(self, 'float_listener') and self.float_listener:
            try:
                self.float_listener.stop()
            except:
                pass
        self.setup_float_global_hotkeys()

    def refresh_current_page(self):
        """刷新当前页面的颜色"""
        # 刷新所有页面
        for page_name, page_frame in self.pages.items():
            # 更新页面背景色
            page_frame.configure(bg=self.bg_color)

            # 递归更新所有子控件背景色
            def update_widget_bg(widget):
                try:
                    if isinstance(widget, (tk.Frame, tk.LabelFrame, tk.Label)):
                        if widget.master != self.nav_frame:
                            widget.configure(bg=self.bg_color)
                    elif isinstance(widget, tk.Button):
                        if widget.cget('bg') not in ["#1F7A48", "#dc2626", "#F59E0B", "#95A5A6", "#E0E0E0"]:
                            widget.configure(bg=self.bg_color)
                    for child in widget.winfo_children():
                        update_widget_bg(child)
                except:
                    pass

            update_widget_bg(page_frame)


numbered_print(f"[{get_time_str()}] 窗口 \"根号七的工具箱{VERSION}{VERNO}\" 初始化完成")

# ===================== 程序启动入口 ==========================

if __name__ == "__main__":

    if sys.platform == "win32":
        import ctypes

        try:
            ctypes.windll.shcore.SetProcessDpiAwareness(1)
        except:
            pass

    root = tk.Tk()
    app = ToolboxApp(root)
    numbered_print(f"[{get_time_str()}] 窗口 \"根号七的工具箱{VERSION}{VERNO}\" 弹窗完成")
    root.mainloop()

# ============================================================

# 由三分之根号七制作
# B站 根号七大玉 -> https://space.bilibili.com/3493288684292639
# QQ 根号圆周率 -> https://qm.qq.com/q/LSNcYCkvmK 群号1083170749

# ============================================================