You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
9.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import tkinter as tk
import customtkinter as ctk
class UserAuthUI:
def __init__(self, app):
self.app = app
self.root = app.root
self.auth = app.auth
self.login_window = None
self.username_entry = None
self.password_entry = None
self.login_error_label = None
def show_login_window(self):
"""显示登录窗口"""
# 隐藏主窗口
self.root.withdraw()
# 创建登录窗口
self.login_window = ctk.CTkToplevel(self.root)
self.login_window.title("登录 - DeepSeek AI Assistant")
self.login_window.geometry("400x350")
self.login_window.resizable(False, False)
self.login_window.protocol("WM_DELETE_WINDOW", self.root.destroy)
# 设置窗口居中
self.login_window.update_idletasks()
width = self.login_window.winfo_width()
height = self.login_window.winfo_height()
x = (self.login_window.winfo_screenwidth() // 2) - (width // 2)
y = (self.login_window.winfo_screenheight() // 2) - (height // 2)
self.login_window.geometry(f"{width}x{height}+{x}+{y}")
# 标题
title_label = ctk.CTkLabel(
self.login_window,
text="DeepSeek AI Assistant",
font=ctk.CTkFont(size=24, weight="bold")
)
title_label.pack(pady=30)
# 登录表单框架
form_frame = ctk.CTkFrame(self.login_window, fg_color="transparent")
form_frame.pack(pady=10, padx=20, fill="both", expand=True)
# 用户名
self.username_entry = ctk.CTkEntry(
form_frame,
placeholder_text="用户名",
width=300,
height=40,
corner_radius=8
)
self.username_entry.pack(pady=(10, 5))
# 密码
self.password_entry = ctk.CTkEntry(
form_frame,
placeholder_text="密码",
show="*",
width=300,
height=40,
corner_radius=8
)
self.password_entry.pack(pady=(5, 10))
# 错误提示
self.login_error_label = ctk.CTkLabel(
form_frame,
text="",
text_color="red",
font=ctk.CTkFont(size=12)
)
self.login_error_label.pack(pady=(5, 10))
# 登录按钮
login_btn = ctk.CTkButton(
form_frame,
text="登录",
command=self._handle_login,
width=300,
height=40,
corner_radius=8,
fg_color="#0078d4",
hover_color="#106ebe"
)
login_btn.pack(pady=(5, 5))
# 注册按钮
register_btn = ctk.CTkButton(
form_frame,
text="注册新用户",
command=self._show_register_window,
width=300,
height=40,
corner_radius=8,
fg_color="#333333",
hover_color="#444444"
)
register_btn.pack(pady=(5, 10))
# 绑定回车事件
self.username_entry.bind("<Return>", lambda e: self.password_entry.focus())
self.password_entry.bind("<Return>", lambda e: self._handle_login())
def _show_register_window(self):
"""显示注册窗口"""
# 隐藏登录窗口
self.login_window.withdraw()
# 创建注册窗口
register_window = ctk.CTkToplevel(self.root)
register_window.title("注册 - DeepSeek AI Assistant")
register_window.geometry("400x400")
register_window.resizable(False, False)
register_window.protocol("WM_DELETE_WINDOW", self.root.destroy)
# 设置窗口居中
register_window.update_idletasks()
width = register_window.winfo_width()
height = register_window.winfo_height()
x = (register_window.winfo_screenwidth() // 2) - (width // 2)
y = (register_window.winfo_screenheight() // 2) - (height // 2)
register_window.geometry(f"{width}x{height}+{x}+{y}")
# 标题
title_label = ctk.CTkLabel(
register_window,
text="创建新账户",
font=ctk.CTkFont(size=20, weight="bold")
)
title_label.pack(pady=20)
# 注册表单框架
form_frame = ctk.CTkFrame(register_window, fg_color="transparent")
form_frame.pack(pady=10, padx=20, fill="both", expand=True)
# 用户名
username_entry = ctk.CTkEntry(
form_frame,
placeholder_text="用户名",
width=300,
height=40,
corner_radius=8
)
username_entry.pack(pady=(10, 5))
# 密码
password_entry = ctk.CTkEntry(
form_frame,
placeholder_text="密码至少6位",
show="*",
width=300,
height=40,
corner_radius=8
)
password_entry.pack(pady=(5, 5))
# 确认密码
confirm_entry = ctk.CTkEntry(
form_frame,
placeholder_text="确认密码",
show="*",
width=300,
height=40,
corner_radius=8
)
confirm_entry.pack(pady=(5, 5))
# 邮箱(可选)
email_entry = ctk.CTkEntry(
form_frame,
placeholder_text="邮箱(可选)",
width=300,
height=40,
corner_radius=8
)
email_entry.pack(pady=(5, 10))
# 错误提示
error_label = ctk.CTkLabel(
form_frame,
text="",
text_color="red",
font=ctk.CTkFont(size=12)
)
error_label.pack(pady=(5, 10))
def _handle_register():
"""处理注册"""
username = username_entry.get().strip()
password = password_entry.get().strip()
confirm = confirm_entry.get().strip()
email = email_entry.get().strip()
# 验证输入
if not username:
error_label.configure(text="请输入用户名")
return
if not password:
error_label.configure(text="请输入密码")
return
if password != confirm:
error_label.configure(text="两次输入的密码不一致")
return
# 调用注册方法
success, message = self.auth.register(username, password, email)
if success:
error_label.configure(text=message, text_color="green")
# 3秒后关闭注册窗口返回登录窗口
register_window.after(1500, lambda: [register_window.destroy(), self.login_window.deiconify()])
else:
error_label.configure(text=message)
# 注册按钮
register_btn = ctk.CTkButton(
form_frame,
text="注册",
command=_handle_register,
width=300,
height=40,
corner_radius=8,
fg_color="#0078d4",
hover_color="#106ebe"
)
register_btn.pack(pady=(5, 5))
# 返回登录按钮
back_btn = ctk.CTkButton(
form_frame,
text="返回登录",
command=lambda: [register_window.destroy(), self.login_window.deiconify()],
width=300,
height=40,
corner_radius=8,
fg_color="#333333",
hover_color="#444444"
)
back_btn.pack(pady=(5, 10))
# 绑定回车事件
username_entry.bind("<Return>", lambda e: password_entry.focus())
password_entry.bind("<Return>", lambda e: confirm_entry.focus())
confirm_entry.bind("<Return>", lambda e: email_entry.focus())
email_entry.bind("<Return>", lambda e: _handle_register())
def _handle_login(self):
"""处理登录"""
username = self.username_entry.get().strip()
password = self.password_entry.get().strip()
# 验证输入
if not username:
self.login_error_label.configure(text="请输入用户名")
return
if not password:
self.login_error_label.configure(text="请输入密码")
return
# 调用登录方法
success, result = self.auth.login(username, password)
if success:
# 登录成功
session_id = result
# 关闭登录窗口
self.login_window.destroy()
# 设置用户名和session_id
self.app.current_username = username
self.app.current_session_id = session_id
# 显示主窗口并初始化UI
self.root.deiconify()
self.app.init_ui()
else:
# 登录失败
self.login_error_label.configure(text=result)