"""自定义GUI组件""" import tkinter as tk from tkinter import ttk from datetime import datetime class AccountTable(ttk.Treeview): """账号列表表格""" COLUMNS = ('index', 'username', 'email', 'status', 'cookie') def __init__(self, parent, **kwargs): super().__init__( parent, columns=self.COLUMNS, show='headings', selectmode='extended', **kwargs ) # 设置列标题 self.heading('index', text='序号') self.heading('username', text='用户名') self.heading('email', text='邮箱') self.heading('status', text='状态') self.heading('cookie', text='Cookie') # 设置列宽 self.column('index', width=50, minwidth=50, anchor='center') self.column('username', width=150, minwidth=100) self.column('email', width=200, minwidth=150) self.column('status', width=80, minwidth=60, anchor='center') self.column('cookie', width=200, minwidth=100) # 添加滚动条 scrollbar = ttk.Scrollbar(parent, orient='vertical', command=self.yview) self.configure(yscrollcommand=scrollbar.set) scrollbar.pack(side='right', fill='y') # 状态标签样式 self.tag_configure('pending', foreground='gray') self.tag_configure('running', foreground='blue') self.tag_configure('success', foreground='green') self.tag_configure('failed', foreground='red') self.tag_configure('error', foreground='red') def add_account(self, index: int, username: str, email: str): """添加账号到表格""" self.insert('', 'end', iid=str(index), values=( index + 1, username, email, '待登录', '-' ), tags=('pending',)) def update_status(self, index: int, status: str, cookie: str = ''): """更新账号状态""" status_map = { 'pending': ('待登录', 'pending'), 'running': ('登录中...', 'running'), 'success': ('成功', 'success'), 'failed': ('失败', 'failed'), 'error': ('异常', 'error'), } text, tag = status_map.get(status, (status, 'pending')) item_id = str(index) if self.exists(item_id): values = self.item(item_id, 'values') cookie_display = cookie[:30] + '...' if len(cookie) > 30 else cookie self.item(item_id, values=( values[0], values[1], values[2], text, cookie_display if cookie else '-' ), tags=(tag,)) def clear(self): """清空表格""" for item in self.get_children(): self.delete(item) def get_all_items(self): """获取所有项目""" items = [] for item_id in self.get_children(): values = self.item(item_id, 'values') items.append({ 'index': values[0], 'username': values[1], 'email': values[2], 'status': values[3], 'cookie': values[4], }) return items class LogPanel(tk.Text): """日志输出面板""" def __init__(self, parent, **kwargs): super().__init__( parent, wrap='word', state='disabled', font=('Consolas', 10), **kwargs ) # 日志级别颜色 self.tag_configure('info', foreground='#333333') self.tag_configure('success', foreground='#008000') self.tag_configure('warning', foreground='#FF8C00') self.tag_configure('error', foreground='#FF0000') self.tag_configure('debug', foreground='#888888') self.tag_configure('timestamp', foreground='#666666') # 添加滚动条 scrollbar = ttk.Scrollbar(parent, orient='vertical', command=self.yview) self.configure(yscrollcommand=scrollbar.set) scrollbar.pack(side='right', fill='y') def append_log(self, level: str, message: str): """添加日志""" self.configure(state='normal') # 添加时间戳 timestamp = datetime.now().strftime('%H:%M:%S') self.insert('end', f'[{timestamp}] ', 'timestamp') # 添加日志内容 self.insert('end', f'{message}\n', level) # 滚动到底部 self.see('end') self.configure(state='disabled') def clear(self): """清空日志""" self.configure(state='normal') self.delete('1.0', 'end') self.configure(state='disabled') class ImportDialog(tk.Toplevel): """导入对话框""" def __init__(self, parent): super().__init__(parent) self.title('从文件导入') self.geometry('400x150') self.resizable(False, False) self.transient(parent) self.grab_set() # 居中显示 self.update_idletasks() x = (self.winfo_screenwidth() - 400) // 2 y = (self.winfo_screenheight() - 150) // 2 self.geometry(f'+{x}+{y}') self.filepath = None self.result = None # 文件路径 frame = ttk.Frame(self, padding=20) frame.pack(fill='both', expand=True) ttk.Label(frame, text='选择账号文件(每行一个,格式:用户名|密码|邮箱|邮箱密码)').pack(anchor='w') path_frame = ttk.Frame(frame) path_frame.pack(fill='x', pady=(10, 0)) self.path_var = tk.StringVar() ttk.Entry(path_frame, textvariable=self.path_var, state='readonly').pack(side='left', fill='x', expand=True) ttk.Button(path_frame, text='浏览', command=self._browse).pack(side='left', padx=(5, 0)) # 按钮 btn_frame = ttk.Frame(frame) btn_frame.pack(fill='x', pady=(20, 0)) ttk.Button(btn_frame, text='确定', command=self._confirm).pack(side='right', padx=(5, 0)) ttk.Button(btn_frame, text='取消', command=self._cancel).pack(side='right') def _browse(self): """浏览文件""" from tkinter import filedialog filepath = filedialog.askopenfilename( title='选择账号文件', filetypes=[('文本文件', '*.txt'), ('所有文件', '*.*')] ) if filepath: self.path_var.set(filepath) self.filepath = filepath def _confirm(self): """确认""" if not self.filepath: tk.messagebox.showwarning('提示', '请选择文件') return self.result = self.filepath self.destroy() def _cancel(self): """取消""" self.destroy()