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.

410 lines
16 KiB

import tkinter as tk
import customtkinter as ctk
from config.config import config_manager
class SettingsComponent:
"""设置界面组件"""
def __init__(self, parent_frame, app, api):
self.parent_frame = parent_frame
self.app = app
self.api = api
self.settings_frame = None
self.scrollable_frame = None
def _create_settings_interface(self):
"""创建设置界面"""
if self.settings_frame is None:
self.settings_frame = ctk.CTkFrame(self.parent_frame, fg_color="#1e1e1e")
# 创建滑动条
self.scrollable_frame = ctk.CTkScrollableFrame(self.settings_frame, fg_color="#1e1e1e")
self.scrollable_frame.pack(fill="both", expand=True, padx=20, pady=20)
# 设置标题
settings_title = ctk.CTkLabel(
self.scrollable_frame,
text="系统设置",
font=ctk.CTkFont(family="Microsoft YaHei UI", size=24, weight="bold"),
text_color="#ffffff"
)
settings_title.pack(pady=20)
# 账户信息部分
account_frame = ctk.CTkFrame(self.scrollable_frame, fg_color="#252525", corner_radius=10)
account_frame.pack(fill="x", padx=20, pady=10)
account_title = ctk.CTkLabel(
account_frame,
text="账户信息",
font=ctk.CTkFont(family="Microsoft YaHei UI", size=18, weight="bold"),
text_color="#ffffff"
)
account_title.pack(pady=10, padx=20, anchor="w")
# 用户名
username_label = ctk.CTkLabel(
account_frame,
text="用户名:",
font=ctk.CTkFont(family="Microsoft YaHei UI", size=14),
text_color="#cccccc"
)
username_label.pack(pady=(0, 5), padx=20, anchor="w")
username_value = ctk.CTkLabel(
account_frame,
text=self.app.current_username if self.app.current_username else "未登录",
font=ctk.CTkFont(family="Microsoft YaHei UI", size=14),
text_color="#ffffff"
)
username_value.pack(pady=(0, 10), padx=20, anchor="w")
# 会话ID
session_id_label = ctk.CTkLabel(
account_frame,
text="会话ID:",
font=ctk.CTkFont(family="Microsoft YaHei UI", size=14),
text_color="#aaaaaa"
)
session_id_label.pack(pady=(0, 5), padx=20, anchor="w")
session_id_value = ctk.CTkLabel(
account_frame,
text=self.app.current_session_id if self.app.current_session_id else "",
font=ctk.CTkFont(family="Microsoft YaHei UI", size=14),
text_color="#ffffff"
)
session_id_value.pack(pady=(0, 10), padx=20, anchor="w")
# 模型设置部分
model_frame = ctk.CTkFrame(self.scrollable_frame, fg_color="#252525", corner_radius=10)
model_frame.pack(fill="x", padx=20, pady=10)
model_title = ctk.CTkLabel(
model_frame,
text="模型设置",
font=ctk.CTkFont(family="Microsoft YaHei UI", size=18, weight="bold"),
text_color="#ffffff"
)
model_title.pack(pady=10, padx=20, anchor="w")
# 模型选择
model_label = ctk.CTkLabel(
model_frame,
text="当前模型:",
font=ctk.CTkFont(family="Microsoft YaHei UI", size=14),
text_color="#aaaaaa"
)
model_label.pack(pady=(0, 5), padx=20, anchor="w")
self.model_var = tk.StringVar(value=self.api.model)
self.model_combo = ctk.CTkComboBox(
model_frame,
variable=self.model_var,
values=["deepseek-chat", "deepseek-coder"],
width=200,
corner_radius=8,
fg_color="#333333",
button_color="#444444",
button_hover_color="#555555"
)
self.model_combo.pack(pady=(0, 10), padx=20, anchor="w")
# 回复随机性 (Temperature)
temperature_label = ctk.CTkLabel(
model_frame,
text=f"回复随机性: {config_manager.get_temperature():.2f}",
font=ctk.CTkFont(family="Microsoft YaHei UI", size=14),
text_color="#aaaaaa"
)
temperature_label.pack(pady=(0, 5), padx=20, anchor="w")
self.temperature_slider = ctk.CTkSlider(
model_frame,
from_=0.0,
to=1.0,
number_of_steps=100,
command=lambda value: temperature_label.configure(text=f"回复随机性: {value:.2f}"),
width=200,
fg_color="#333333",
progress_color="#0078d4"
)
self.temperature_slider.set(config_manager.get_temperature())
self.temperature_slider.pack(pady=(0, 15), padx=20, anchor="w")
# 最大回复长度 (Max Tokens)
max_tokens_label = ctk.CTkLabel(
model_frame,
text=f"最大回复长度: {config_manager.get_max_tokens()}",
font=ctk.CTkFont(family="Microsoft YaHei UI", size=14),
text_color="#aaaaaa"
)
max_tokens_label.pack(pady=(0, 5), padx=20, anchor="w")
self.max_tokens_slider = ctk.CTkSlider(
model_frame,
from_=128,
to=2048,
number_of_steps=7,
command=lambda value: max_tokens_label.configure(text=f"最大回复长度: {int(value)}"),
width=200,
fg_color="#333333",
progress_color="#0078d4"
)
self.max_tokens_slider.set(config_manager.get_max_tokens())
self.max_tokens_slider.pack(pady=(0, 15), padx=20, anchor="w")
# API设置部分
api_frame = ctk.CTkFrame(self.scrollable_frame, fg_color="#252525", corner_radius=10)
api_frame.pack(fill="x", padx=20, pady=10)
api_title = ctk.CTkLabel(
api_frame,
text="API设置",
font=ctk.CTkFont(family="Microsoft YaHei UI", size=18, weight="bold"),
text_color="#ffffff"
)
api_title.pack(pady=10, padx=20, anchor="w")
# API类型选择
api_type_frame = ctk.CTkFrame(api_frame, fg_color="transparent")
api_type_frame.pack(pady=(0, 15), padx=20, anchor="w")
self.api_type_var = tk.StringVar(value="default")
default_api_radio = ctk.CTkRadioButton(
api_type_frame,
text="默认API",
variable=self.api_type_var,
value="default",
command=self._toggle_api_type,
text_color="#ffffff",
fg_color="#0078d4"
)
default_api_radio.pack(side="left", padx=10)
custom_api_radio = ctk.CTkRadioButton(
api_type_frame,
text="自定义API",
variable=self.api_type_var,
value="custom",
command=self._toggle_api_type,
text_color="#ffffff",
fg_color="#0078d4"
)
custom_api_radio.pack(side="left", padx=10)
# API URL
self.api_url_label = ctk.CTkLabel(
api_frame,
text="API URL:",
font=ctk.CTkFont(family="Microsoft YaHei UI", size=14),
text_color="#aaaaaa"
)
self.api_url_label.pack(pady=(0, 5), padx=20, anchor="w")
self.api_url_entry = ctk.CTkEntry(
api_frame,
placeholder_text="请输入API URL",
width=300,
height=40,
corner_radius=8,
fg_color="#333333",
text_color="#ffffff",
placeholder_text_color="#aaaaaa",
state="disabled"
)
self.api_url_entry.pack(pady=(0, 10), padx=20, anchor="w")
# API密钥
self.api_key_label = ctk.CTkLabel(
api_frame,
text="API密钥:",
font=ctk.CTkFont(family="Microsoft YaHei UI", size=14),
text_color="#aaaaaa"
)
self.api_key_label.pack(pady=(0, 5), padx=20, anchor="w")
self.api_key_entry = ctk.CTkEntry(
api_frame,
placeholder_text="请输入API密钥",
width=300,
height=40,
corner_radius=8,
fg_color="#333333",
text_color="#ffffff",
placeholder_text_color="#aaaaaa",
state="disabled"
)
self.api_key_entry.pack(pady=(0, 15), padx=20, anchor="w")
# AI提示设置部分
ai_prompt_frame = ctk.CTkFrame(self.scrollable_frame, fg_color="#252525", corner_radius=10)
ai_prompt_frame.pack(fill="x", padx=20, pady=10)
ai_prompt_title = ctk.CTkLabel(
ai_prompt_frame,
text="AI提示设置",
font=ctk.CTkFont(family="Microsoft YaHei UI", size=18, weight="bold"),
text_color="#ffffff"
)
ai_prompt_title.pack(pady=10, padx=20, anchor="w")
# 日程助手提示
schedule_prompt_label = ctk.CTkLabel(
ai_prompt_frame,
text="日程助手系统提示:",
font=ctk.CTkFont(family="Microsoft YaHei UI", size=14),
text_color="#aaaaaa"
)
schedule_prompt_label.pack(pady=(0, 5), padx=20, anchor="w")
self.schedule_prompt_textbox = ctk.CTkTextbox(
ai_prompt_frame,
height=100,
width=500,
corner_radius=8,
fg_color="#333333",
text_color="#ffffff"
)
self.schedule_prompt_textbox.pack(pady=(0, 15), padx=20, anchor="w")
self.schedule_prompt_textbox.insert("1.0", config_manager.get_schedule_assistant_prompt())
# 待办助手提示
todo_prompt_label = ctk.CTkLabel(
ai_prompt_frame,
text="待办助手系统提示:",
font=ctk.CTkFont(family="Microsoft YaHei UI", size=14),
text_color="#aaaaaa"
)
todo_prompt_label.pack(pady=(0, 5), padx=20, anchor="w")
self.todo_prompt_textbox = ctk.CTkTextbox(
ai_prompt_frame,
height=100,
width=500,
corner_radius=8,
fg_color="#333333",
text_color="#ffffff"
)
self.todo_prompt_textbox.pack(pady=(0, 15), padx=20, anchor="w")
self.todo_prompt_textbox.insert("1.0", config_manager.get_todo_assistant_prompt())
# 日志设置部分
logs_frame = ctk.CTkFrame(self.scrollable_frame, fg_color="#252525", corner_radius=10)
logs_frame.pack(fill="x", padx=20, pady=10)
logs_title = ctk.CTkLabel(
logs_frame,
text="系统日志",
font=ctk.CTkFont(family="Microsoft YaHei UI", size=18, weight="bold"),
text_color="#ffffff"
)
logs_title.pack(pady=10, padx=20, anchor="w")
# 查看日志按钮
view_logs_btn = ctk.CTkButton(
logs_frame,
text="查看日志",
command=self.app._show_logs,
width=150,
height=40,
corner_radius=8,
fg_color="#005a9e",
hover_color="#004a80"
)
view_logs_btn.pack(pady=10, padx=20, anchor="w")
# 保存设置按钮(移到最底部)
save_btn = ctk.CTkButton(
self.scrollable_frame,
text="保存设置",
command=self._save_settings,
width=200,
height=40,
corner_radius=8,
fg_color="#005a9e",
hover_color="#004a80"
)
save_btn.pack(pady=30, padx=20, anchor="center")
def _toggle_api_type(self):
"""切换API类型"""
api_type = self.api_type_var.get()
if api_type == "default":
self.api_url_entry.configure(state="disabled")
self.api_key_entry.configure(state="disabled")
else:
self.api_url_entry.configure(state="normal")
self.api_key_entry.configure(state="normal")
def _save_settings(self):
"""保存设置"""
# 获取当前设置
selected_model = self.model_var.get()
api_type = self.api_type_var.get()
api_url = self.api_url_entry.get() if api_type == "custom" else ""
api_key = self.api_key_entry.get() if api_type == "custom" else ""
temperature = self.temperature_slider.get()
max_tokens = int(self.max_tokens_slider.get())
# 获取AI提示设置
schedule_prompt = self.schedule_prompt_textbox.get("1.0", "end-1c")
todo_prompt = self.todo_prompt_textbox.get("1.0", "end-1c")
# 更新API模型
self.api.model = selected_model
config_manager.set_default_model(selected_model)
# 更新温度和最大回复长度
config_manager.set_temperature(temperature)
config_manager.set_max_tokens(max_tokens)
# 更新AI提示设置
config_manager.set_schedule_assistant_prompt(schedule_prompt)
config_manager.set_todo_assistant_prompt(todo_prompt)
# 更新API设置
if api_type == "custom":
if api_url and api_key:
# 这里可以添加实际的API设置更新逻辑
self.api.api_url = api_url
self.api.api_key = api_key
config_manager.set_api_url(api_url)
config_manager.set_api_key(api_key)
print(f"更新API设置: URL={api_url}, Key={api_key}")
success_msg = "所有设置已保存"
else:
success_msg = "自定义API需要填写完整的URL和密钥"
else:
# 恢复默认API设置
self.api.api_url = ""
self.api.api_key = ""
config_manager.set_api_url("https://api.deepseek.com/v1/chat/completions")
success_msg = "所有设置已保存"
# 显示保存成功提示
self.save_success_label = ctk.CTkLabel(
self.scrollable_frame,
text=success_msg,
font=ctk.CTkFont(family="Microsoft YaHei UI", size=14),
text_color="#34a853"
)
self.save_success_label.pack(pady=(0, 10))
# 3秒后自动移除提示
self.settings_frame.after(3000, self.save_success_label.destroy)
def get_settings_frame(self):
"""获取设置帧"""
return self.settings_frame
def show(self):
"""显示设置界面"""
self._create_settings_interface()
self.settings_frame.pack(side="right", fill="both", expand=True, padx=(0, 5))
def hide(self):
"""隐藏设置界面"""
if self.settings_frame:
self.settings_frame.pack_forget()