#!/usr/bin/env python # -*- coding: utf-8 -*- """ 设置标签页 管理系统配置(ERP、数据库、浏览器、路径等)。 """ import tkinter as tk from tkinter import ttk, messagebox import pyodbc from gui.config_manager import ConfigManager class SettingsTab(ttk.Frame): """设置标签页""" def __init__(self, parent, config: ConfigManager): """ 初始化设置标签页 Args: parent: 父容器 config: 配置管理器 """ super().__init__(parent) self.config = config self.create_widgets() self.load_settings() def create_widgets(self): """创建界面组件""" # 创建主容器,带滚动条 canvas = tk.Canvas(self) scrollbar = ttk.Scrollbar(self, orient="vertical", command=canvas.yview) scrollable_frame = ttk.Frame(canvas) scrollable_frame.bind( "", lambda e: canvas.configure(scrollregion=canvas.bbox("all")) ) canvas.create_window((0, 0), window=scrollable_frame, anchor="nw") canvas.configure(yscrollcommand=scrollbar.set) # ERP 配置组 self._create_erp_group(scrollable_frame) # 数据库配置组 self._create_database_group(scrollable_frame) # 浏览器配置组 self._create_browser_group(scrollable_frame) # 路径配置组 self._create_paths_group(scrollable_frame) # 处理配置组 self._create_extraction_group(scrollable_frame) # 按钮区域 button_frame = ttk.Frame(scrollable_frame) button_frame.grid(row=5, column=0, columnspan=2, pady=20, sticky="ew") ttk.Button(button_frame, text="测试 ERP 连接", command=self.test_erp_connection).pack(side="left", padx=5) ttk.Button(button_frame, text="测试数据库连接", command=self.test_db_connection).pack(side="left", padx=5) ttk.Button(button_frame, text="保存设置", command=self.save_settings).pack(side="left", padx=5) ttk.Button(button_frame, text="恢复默认", command=self.reset_defaults).pack(side="left", padx=5) # 布局 canvas.grid(row=0, column=0, sticky="nsew") scrollbar.grid(row=0, column=1, sticky="ns") self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) def _create_erp_group(self, parent): """创建 ERP 配置组""" group = ttk.LabelFrame(parent, text="ERP 系统配置", padding=10) group.grid(row=0, column=0, columnspan=2, pady=10, padx=10, sticky="ew") # URL ttk.Label(group, text="ERP URL:").grid(row=0, column=0, sticky="w", pady=5) self.erp_url_var = tk.StringVar() ttk.Entry(group, textvariable=self.erp_url_var, width=50).grid(row=0, column=1, pady=5, sticky="ew") # 用户名 ttk.Label(group, text="用户名:").grid(row=1, column=0, sticky="w", pady=5) self.erp_username_var = tk.StringVar() ttk.Entry(group, textvariable=self.erp_username_var, width=50).grid(row=1, column=1, pady=5, sticky="ew") # 密码 ttk.Label(group, text="密码:").grid(row=2, column=0, sticky="w", pady=5) self.erp_password_var = tk.StringVar() entry = ttk.Entry(group, textvariable=self.erp_password_var, width=50, show="*") entry.grid(row=2, column=1, pady=5, sticky="ew") group.columnconfigure(1, weight=1) def _create_database_group(self, parent): """创建数据库配置组""" group = ttk.LabelFrame(parent, text="数据库配置", padding=10) group.grid(row=1, column=0, columnspan=2, pady=10, padx=10, sticky="ew") # 服务器 ttk.Label(group, text="服务器:").grid(row=0, column=0, sticky="w", pady=5) self.db_server_var = tk.StringVar() ttk.Entry(group, textvariable=self.db_server_var, width=50).grid(row=0, column=1, pady=5, sticky="ew") # 数据库名 ttk.Label(group, text="数据库:").grid(row=1, column=0, sticky="w", pady=5) self.db_name_var = tk.StringVar() ttk.Entry(group, textvariable=self.db_name_var, width=50).grid(row=1, column=1, pady=5, sticky="ew") # 用户名 ttk.Label(group, text="用户名:").grid(row=2, column=0, sticky="w", pady=5) self.db_username_var = tk.StringVar() ttk.Entry(group, textvariable=self.db_username_var, width=50).grid(row=2, column=1, pady=5, sticky="ew") # 密码 ttk.Label(group, text="密码:").grid(row=3, column=0, sticky="w", pady=5) self.db_password_var = tk.StringVar() entry = ttk.Entry(group, textvariable=self.db_password_var, width=50, show="*") entry.grid(row=3, column=1, pady=5, sticky="ew") group.columnconfigure(1, weight=1) def _create_browser_group(self, parent): """创建浏览器配置组""" group = ttk.LabelFrame(parent, text="浏览器设置", padding=10) group.grid(row=2, column=0, pady=10, padx=10, sticky="ew") self.browser_headless_var = tk.BooleanVar() ttk.Checkbutton(group, text="无头模式 (不显示浏览器)", variable=self.browser_headless_var).grid(row=0, column=0, sticky="w", pady=5) self.browser_ignore_https_var = tk.BooleanVar() ttk.Checkbutton(group, text="忽略 HTTPS 错误", variable=self.browser_ignore_https_var).grid(row=1, column=0, sticky="w", pady=5) self.browser_auto_close_var = tk.BooleanVar() ttk.Checkbutton(group, text="操作完成后自动关闭浏览器", variable=self.browser_auto_close_var).grid(row=2, column=0, sticky="w", pady=5) def _create_paths_group(self, parent): """创建路径配置组""" group = ttk.LabelFrame(parent, text="路径设置", padding=10) group.grid(row=2, column=1, pady=10, padx=10, sticky="nsew") from gui.widgets import FileSelector # 数据目录 ttk.Label(group, text="数据目录:").grid(row=0, column=0, sticky="w", pady=5) self.data_dir_selector = FileSelector( group, label_text="", file_type="directory", initial_dir="D:/python/playwrite/data/" ) self.data_dir_selector.grid(row=1, column=0, columnspan=2, sticky="ew", pady=5) # 默认输出文件 ttk.Label(group, text="默认输出文件:").grid(row=2, column=0, sticky="w", pady=5) self.default_output_var = tk.StringVar() ttk.Entry(group, textvariable=self.default_output_var, width=40).grid(row=3, column=0, columnspan=2, sticky="ew", pady=5) group.columnconfigure(0, weight=1) def _create_extraction_group(self, parent): """创建处理配置组""" group = ttk.LabelFrame(parent, text="数据提取设置", padding=10) group.grid(row=3, column=0, columnspan=2, pady=10, padx=10, sticky="ew") # 批次大小 ttk.Label(group, text="批次大小:").grid(row=0, column=0, sticky="w", pady=5) self.batch_size_var = tk.IntVar(value=100) ttk.Spinbox(group, from_=10, to=500, textvariable=self.batch_size_var, width=10).grid(row=0, column=1, sticky="w", pady=5) # 详细日志 self.verbose_var = tk.BooleanVar() ttk.Checkbutton(group, text="启用详细日志", variable=self.verbose_var).grid(row=1, column=0, columnspan=2, sticky="w", pady=5) # 自动转换 self.auto_convert_var = tk.BooleanVar() ttk.Checkbutton(group, text="自动转换 Excel 格式", variable=self.auto_convert_var).grid(row=2, column=0, columnspan=2, sticky="w", pady=5) # 合并批次 self.merge_batches_var = tk.BooleanVar() ttk.Checkbutton(group, text="自动合并批次数据", variable=self.merge_batches_var).grid(row=3, column=0, columnspan=2, sticky="w", pady=5) def load_settings(self): """从配置加载设置到界面""" # ERP 设置 self.erp_url_var.set(self.config.get('erp.url', '')) self.erp_username_var.set(self.config.get('erp.username', '')) self.erp_password_var.set(self.config.get('erp.password', '')) # 数据库设置 self.db_server_var.set(self.config.get('database.server', '')) self.db_name_var.set(self.config.get('database.database', '')) self.db_username_var.set(self.config.get('database.username', '')) self.db_password_var.set(self.config.get('database.password', '')) # 浏览器设置 self.browser_headless_var.set(self.config.get('browser.headless', True)) self.browser_ignore_https_var.set(self.config.get('browser.ignore_https_errors', True)) self.browser_auto_close_var.set(self.config.get('browser.auto_close', True)) # 路径设置 self.data_dir_selector.set(self.config.get('paths.data_dir', '')) self.default_output_var.set(self.config.get('paths.default_output', '')) # 处理设置 self.batch_size_var.set(self.config.get('extraction.batch_size', 100)) self.verbose_var.set(self.config.get('extraction.verbose', True)) self.auto_convert_var.set(self.config.get('extraction.auto_convert', True)) self.merge_batches_var.set(self.config.get('extraction.merge_batches', True)) def save_settings(self): """保存界面设置到配置""" # ERP 设置 self.config.set('erp.url', self.erp_url_var.get()) self.config.set('erp.username', self.erp_username_var.get()) self.config.set('erp.password', self.erp_password_var.get()) # 数据库设置 self.config.set('database.server', self.db_server_var.get()) self.config.set('database.database', self.db_name_var.get()) self.config.set('database.username', self.db_username_var.get()) self.config.set('database.password', self.db_password_var.get()) # 浏览器设置 self.config.set('browser.headless', self.browser_headless_var.get()) self.config.set('browser.ignore_https_errors', self.browser_ignore_https_var.get()) self.config.set('browser.auto_close', self.browser_auto_close_var.get()) # 路径设置 self.config.set('paths.data_dir', self.data_dir_selector.get()) self.config.set('paths.default_output', self.default_output_var.get()) # 处理设置 self.config.set('extraction.batch_size', self.batch_size_var.get()) self.config.set('extraction.verbose', self.verbose_var.get()) self.config.set('extraction.auto_convert', self.auto_convert_var.get()) self.config.set('extraction.merge_batches', self.merge_batches_var.get()) # 保存到文件 if self.config.save(): messagebox.showinfo("成功", "设置已保存") else: messagebox.showerror("错误", "保存设置失败") def test_db_connection(self): """测试数据库连接""" try: conn_str = ( f"DRIVER={{ODBC Driver 18 for SQL Server}};" f"SERVER={self.db_server_var.get()};" f"DATABASE={self.db_name_var.get()};" f"UID={self.db_username_var.get()};" f"PWD={self.db_password_var.get()};" f"TrustServerCertificate=yes;" ) conn = pyodbc.connect(conn_str, timeout=5) conn.close() messagebox.showinfo("成功", "数据库连接测试成功!") except Exception as e: messagebox.showerror("错误", f"数据库连接失败:\n{str(e)}") def test_erp_connection(self): """测试 ERP 连接""" # ERP 连接测试需要实际启动浏览器 messagebox.showinfo("提示", "ERP 连接测试将在数据提取功能中自动验证") def reset_defaults(self): """恢复默认设置""" if messagebox.askyesno("确认", "确定要恢复默认设置吗?"): self.config.reset_to_defaults() self.load_settings() messagebox.showinfo("成功", "已恢复默认设置")