diff --git a/ui/main_window.py b/ui/main_window.py index 382223e..0e89687 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -7,6 +7,8 @@ import traceback import customtkinter as ctk import tkinter as tk from tkinter import filedialog, messagebox +from .role_library import RoleLibrary +from llm_adapters import create_llm_adapter from config_manager import load_config, save_config, test_llm_config, test_embedding_config from utils import read_file, save_string_to_txt, clear_file_content @@ -222,6 +224,87 @@ class NovelGeneratorGUI: if selected_dir: self.filepath_var.set(selected_dir) + def show_character_import_window(self): + """显示角色导入窗口""" + import_window = ctk.CTkToplevel(self.master) + import_window.title("导入角色信息") + import_window.geometry("600x500") + import_window.transient(self.master) # 设置为父窗口的临时窗口 + import_window.grab_set() # 保持窗口在顶层 + + # 主容器 + main_frame = ctk.CTkFrame(import_window) + main_frame.pack(fill="both", expand=True, padx=10, pady=10) + + # 滚动容器 + scroll_frame = ctk.CTkScrollableFrame(main_frame) + scroll_frame.pack(fill="both", expand=True, padx=5, pady=5) + + # 获取角色库路径 + role_lib_path = os.path.join(self.filepath_var.get().strip(), "角色库") + self.selected_roles = [] # 存储选中的角色名称 + + # 动态加载角色分类 + if os.path.exists(role_lib_path): + for category in os.listdir(role_lib_path): + category_path = os.path.join(role_lib_path, category) + if os.path.isdir(category_path): + # 添加分类标签 + category_label = ctk.CTkLabel(scroll_frame, text=f"【{category}】", font=("Microsoft YaHei", 12, "bold")) + category_label.pack(anchor="w", pady=(10,5)) + + # 添加该分类下的角色 + for role_file in os.listdir(category_path): + if role_file.endswith(".txt"): + role_name = os.path.splitext(role_file)[0] + # 检查是否已存在同名角色 + if not any(name == role_name for _, name in self.selected_roles): + chk = ctk.CTkCheckBox(scroll_frame, text=role_name) + chk.pack(anchor="w", padx=20) + self.selected_roles.append((chk, role_name)) + + # 底部按钮框架 + btn_frame = ctk.CTkFrame(main_frame) + btn_frame.pack(fill="x", pady=10) + + # 选择按钮 + def confirm_selection(): + selected = [name for chk, name in self.selected_roles if chk.get() == 1] + self.char_inv_text.delete("0.0", "end") + self.char_inv_text.insert("0.0", ", ".join(selected)) + import_window.destroy() + + btn_confirm = ctk.CTkButton(btn_frame, text="选择", command=confirm_selection) + btn_confirm.pack(side="left", padx=20) + + # 取消按钮 + btn_cancel = ctk.CTkButton(btn_frame, text="取消", command=import_window.destroy) + btn_cancel.pack(side="right", padx=20) + + def show_role_library(self): + save_path = self.filepath_var.get().strip() + if not save_path: + messagebox.showwarning("警告", "请先设置保存路径") + return + + # 初始化LLM适配器 + llm_adapter = create_llm_adapter( + interface_format=self.interface_format_var.get(), + base_url=self.base_url_var.get(), + model_name=self.model_name_var.get(), + api_key=self.api_key_var.get(), + temperature=self.temperature_var.get(), + max_tokens=self.max_tokens_var.get(), + timeout=self.timeout_var.get() + ) + + # 传递LLM适配器实例到角色库 + if hasattr(self, '_role_lib'): + if self._role_lib.window and self._role_lib.window.winfo_exists(): + self._role_lib.window.destroy() + + self._role_lib = RoleLibrary(self.master, save_path, llm_adapter) # 新增参数 + # ----------------- 将导入的各模块函数直接赋给类方法 ----------------- generate_novel_architecture_ui = generate_novel_architecture_ui generate_chapter_blueprint_ui = generate_chapter_blueprint_ui