213 lines
6.6 KiB
Python
213 lines
6.6 KiB
Python
"""自定义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()
|