diff --git a/services/config_manager.py b/services/config_manager.py index 829a682..4fbd39f 100644 --- a/services/config_manager.py +++ b/services/config_manager.py @@ -95,13 +95,22 @@ class ConfigManager: def save(self): """原子写:临时文件 + os.replace,防止写中断导致数据损坏""" + import time config_dir = os.path.dirname(os.path.abspath(CONFIG_FILE)) or "." try: fd, tmp_path = tempfile.mkstemp(dir=config_dir, suffix=".tmp", prefix="config_") try: with os.fdopen(fd, "w", encoding="utf-8") as f: json.dump(self._config, f, indent=4, ensure_ascii=False) - os.replace(tmp_path, CONFIG_FILE) + # Windows 下目标文件被占用时 os.replace 会抛 PermissionError(WinError 5),重试最多 3 次 + for attempt in range(3): + try: + os.replace(tmp_path, CONFIG_FILE) + break + except PermissionError: + if attempt == 2: + raise + time.sleep(0.1) except Exception: try: os.remove(tmp_path) diff --git a/services/llm_service.py b/services/llm_service.py index 26511dc..ebf33d2 100644 --- a/services/llm_service.py +++ b/services/llm_service.py @@ -370,7 +370,7 @@ class LLMService: @staticmethod def get_sd_prompt_guide(sd_model_name: str = None, persona: str = None) -> str: """根据当前 SD 模型 + 人设 生成 LLM 使用的绘图 Prompt 指南(含反 AI 检测指导 + 人设视觉风格)""" - from sd_service import SD_MODEL_PROFILES, detect_model_profile, get_persona_sd_profile + from services.sd_service import SD_MODEL_PROFILES, detect_model_profile, get_persona_sd_profile key = detect_model_profile(sd_model_name) if sd_model_name else "juggernautXL" profile = SD_MODEL_PROFILES.get(key, SD_MODEL_PROFILES["juggernautXL"]) diff --git a/ui/app.py b/ui/app.py index 6cc6728..b8a968d 100644 --- a/ui/app.py +++ b/ui/app.py @@ -70,7 +70,7 @@ def _fn_topic_recommend(model_name): def _fn_batch_generate(model_name, topics, style, sd_model_name, persona_text, template_name): """批量生成文案并入草稿队列""" - pq = PublishQueue() + pq = PublishQueue("xhs_workspace") return batch_generate_copy( model=model_name, topics=topics, diff --git a/ui/tab_create.py b/ui/tab_create.py index 20ba138..76f0918 100644 --- a/ui/tab_create.py +++ b/ui/tab_create.py @@ -83,6 +83,7 @@ def build_tab( label="封面图策略", value="人物特写", info="影响 SD 构图和尺寸", + interactive=True, ) quality_mode = gr.Radio( sd_preset_names,