Files
live-hub-py/gui/widgets.py
T
2026-06-21 23:25:08 +08:00

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()