fix:优化配置存储

This commit is contained in:
2026-01-30 00:19:09 +08:00
parent 6a0c826a06
commit 02cbd256d8
18 changed files with 228 additions and 420 deletions

View File

@@ -1,6 +1,9 @@
import os
import sys
from loguru import logger
from nicegui import app
# 1. 处理读取库
try:
import tomllib as toml_read # Python 3.11+
@@ -39,53 +42,69 @@ def get_resource_path(relative_path):
return external_path
def init_storage():
"""如果 storage 是空的,则注入默认配置"""
cfg = app.storage.general
if "class_name" not in cfg:
logger.info("初始化默认配置...")
default_config = {
"data_folder": os.path.join(get_base_dir(), "data"),
"templates_folder": os.path.join(get_base_dir(), "templates"),
"source_file": "大四班 幼儿学期发展报告.pptx",
"output_folder": "output",
"excel_file": "names.xlsx",
"image_folder": "images",
"fonts_dir": "fonts",
"signature_image": "signature.png",
"class_name": "K4D",
"teachers": ["康璐璐", "冯宇阳", "孙继艳"],
"class_type": 2,
"default_comment": "暂无评语",
"age_group": "大班上学期",
"ai": {
"api_key": "sk-ccb6a1445126f2e56ba50d7622ff350f",
"api_url": "https://apis.iflow.cn/v1/chat/completions",
"model": "deepseek-v3.2",
"prompt": "# Role \n你是一位拥有20年经验的资深幼儿园主班老师。你的文笔温暖、细腻、充满爱意擅长发现每个孩子身上独特的闪光点。你的评语风格是“治愈系”的能让家长读完后感到欣慰并对未来充满希望。\n\n# Goal\n请根据用户提供的【幼儿姓名】、【年龄段/班级】以及【日常表现关键词/评分数据】,撰写一份高质量的学期末成长评语。\n# Constraints & Rules\n1. **严格的格式排版 (Strict Formatting)**:\n- **换行**:正文中间不要随意换行,保持为一段完整的段落。\n2. **称呼处理**:\n- 自动识别用户输入的姓名,去掉姓氏。\n- 例如:“王小明” -> 第一行输出“小明宝贝:”。\n3. **分龄侧重 (根据 Age_Group 调整侧重点)**:\n- **小班 (3-4岁)**:侧重于适应集体生活、情绪稳定性、基本生活自理能力、愿意与老师互动。\n- **中班 (4-5岁)**:侧重于社交互动、分享与合作、动手能力、好奇心、规则意识。\n- **大班 (5-6岁)**:侧重于学习习惯、逻辑思维、领导力、任务意识、幼小衔接准备。\n4. **写作结构 (固定内容)**:\n- **开头**:固定文本必须包含:“{class_type}\n- **正文**:结合【表现关键词】和【性别】,具体描述进步和优点。\n- **结尾**:委婉地提出期望(“如果你能...老师会更为你骄傲”),并送上祝福。\n5. **语气风格**:\n- 积极正面,多用肯定句。\n- 字数控制在 150-250 字之间。\n# Input Format\n- Name {{name}}\n- Age_Group {{class_name}}\n- Traits {{traits}}\n- Sex {{sex}}\n# Output Example\n(假设输入:Name=张图图, Age_Group=小班, Traits=适应能力强, 爱笑, 挑食,Sex=女)\n亲爱的图图宝贝:{class_type}\n你是一个爱笑的小天使,每天早上都能看到你甜甜的笑脸。从一开始的哭鼻子到现在能开心地参与游戏,你的适应能力让老师感到惊喜。不过,老师发现你在吃饭时偶尔会把不喜欢的青菜挑出来哦。如果你能和青菜宝宝做好朋友,把身体练得棒棒的,那就更完美啦!祝可爱的图图宝贝新年快乐,健康成长!\n",
},
}
cfg.update(default_config)
# ==========================================
# 1. 配置加载 (Config Loader)
# ==========================================
def load_config(config_filename="config.toml"):
config_path = get_resource_path(config_filename)
if not os.path.exists(config_path):
# 如果彻底找不到,返回一个最小化的默认值,防止程序奔溃
return {"source_file": "", "ai": {"api_key": ""}, "teachers": []}
def load_config():
try:
with open(config_path, "rb") as f:
data = toml_read.load(f)
config_data = app.storage.general
base_dir = get_base_dir()
# 使用 .get() 安全获取,防止 KeyError: 'paths'
paths = data.get("paths", {})
class_info = data.get("class_info", {})
defaults = data.get("defaults", {})
config = {
"root_path": base_dir,
"data_folder": os.path.join(os.path.join("data")),
# 扁平化映射
"source_file": get_resource_path(
os.path.join("templates", paths.get("source_file", ""))
os.path.join("templates", config_data.get("source_file", ""))
),
"excel_file": get_resource_path(
os.path.join("data", paths.get("excel_file", ""))
os.path.join("data", config_data.get("excel_file", "names"))
),
"image_folder": get_resource_path(
os.path.join("data", paths.get("image_folder", ""))
os.path.join("data", config_data.get("image_folder", ""))
),
"fonts_dir": get_resource_path(paths.get("fonts_dir", "fonts")),
"fonts_dir": get_resource_path(config_data.get("fonts_dir", "fonts")),
"output_folder": os.path.join(
base_dir, paths.get("output_folder", "output")
base_dir, config_data.get("output_folder", "output")
),
"signature_image": get_resource_path(
os.path.join("data", paths.get("signature_image", "signature.png"))
os.path.join("data", config_data.get("signature_image", "signature.png"))
),
"class_name": class_info.get("class_name", "未命名班级"),
"teachers": class_info.get("teachers", []),
"class_type": class_info.get("class_type", 0),
"default_comment": defaults.get("default_comment", "暂无评语"),
"age_group": defaults.get("age_group", "大班上学期"),
"ai": data.get(
"class_name": config_data.get("class_name", "未命名班级"),
"teachers": config_data.get("teachers", []),
"class_type": config_data.get("class_type", 0),
"default_comment": config_data.get("default_comment", "暂无评语"),
"age_group": config_data.get("age_group", "大班上学期"),
"ai": config_data.get(
"ai", {"api_key": "", "api_url": "", "model": "", "prompt": ""}
),
}
@@ -94,52 +113,3 @@ def load_config(config_filename="config.toml"):
except Exception as e:
print(f"解析配置文件失败: {e}")
return {}
# ==========================================
# 2. 配置保存 (Config Saver)
# ==========================================
def save_config(config_data, config_filename="config.toml"):
if not toml_write:
return False, "未安装 tomli-w 库,无法保存。请运行 pip install tomli-w"
base_path = get_base_dir()
save_path = os.path.join(base_path, config_filename)
try:
# 将扁平化的数据重新打包成嵌套结构,以适配 load_config 的读取逻辑
new_data = {
"paths": {
"source_file": os.path.basename(config_data.get("source_file", "")),
"output_folder": os.path.basename(
config_data.get("output_folder", "output")
),
"excel_file": os.path.basename(config_data.get("excel_file", "")),
"image_folder": os.path.basename(config_data.get("image_folder", "")),
"fonts_dir": os.path.basename(config_data.get("fonts_dir", "fonts")),
"signature_image": get_resource_path(
os.path.join(
"data", config_data.get("signature_image", "signature.png")
)
),
},
"class_info": {
"class_name": config_data.get("class_name", ""),
"teachers": config_data.get("teachers", []),
"class_type": config_data.get("class_type", 0),
},
"defaults": {
"default_comment": config_data.get("default_comment", ""),
"age_group": config_data.get("age_group", ""),
},
"ai": config_data.get("ai", {}),
}
# 写入文件
with open(save_path, "wb") as f:
f.write(toml_write.dumps(new_data).encode("utf-8"))
return True, f"成功保存到: {save_path}"
except Exception as e:
return False, f"写入失败: {str(e)}"