From 134896fcd22bd3a485e4314e196416953e00d46a Mon Sep 17 00:00:00 2001 From: ila Date: Mon, 15 Jun 2026 16:51:46 +0800 Subject: [PATCH] feat: implement config service with JSON read/write and safe fallback - DEFAULT_CONFIG defines output_format, output_quality, output_dir, last_garment_dir, last_print_dir - load_config(): merges file values with defaults; never raises on missing, damaged, or non-object JSON root - save_config(): creates config/ dir as needed; logs error on failure Co-Authored-By: Claude Sonnet 4.6 --- src/services/config_service.py | 58 +++++++++++++++++++++++++++++++++- tasks.md | 18 +++++------ 2 files changed, 66 insertions(+), 10 deletions(-) diff --git a/src/services/config_service.py b/src/services/config_service.py index 7658296..7594f9f 100644 --- a/src/services/config_service.py +++ b/src/services/config_service.py @@ -1,2 +1,58 @@ +import json +import logging + +logger = logging.getLogger(__name__) + +DEFAULT_CONFIG = { + "output_format": "PNG", # PNG or JPG + "output_quality": 95, # JPG quality 1-95 + "output_dir": "", # empty = use app output/ dir + "last_garment_dir": "", + "last_print_dir": "", +} + +_CONFIG_FILENAME = "app_config.json" + + def load_config(): - return {} + """Load app config from JSON. Returns defaults merged with file values. + + Never raises: missing file → info log + defaults; + damaged file → warning log + defaults. + """ + from services.file_service import get_config_path + config_file = get_config_path(_CONFIG_FILENAME) + + if not config_file.exists(): + logger.info("Config file not found, using defaults: %s", config_file) + return dict(DEFAULT_CONFIG) + + try: + with open(str(config_file), encoding="utf-8") as f: + data = json.load(f) + if not isinstance(data, dict): + raise ValueError("Config root is not a JSON object") + merged = dict(DEFAULT_CONFIG) + merged.update(data) + logger.info("Config loaded from %s", config_file) + return merged + except (json.JSONDecodeError, ValueError) as exc: + logger.warning("Config file damaged (%s), using defaults: %s", exc, config_file) + return dict(DEFAULT_CONFIG) + except OSError as exc: + logger.warning("Config file unreadable (%s), using defaults: %s", exc, config_file) + return dict(DEFAULT_CONFIG) + + +def save_config(data): + """Save config dict to JSON. Logs error on failure, does not raise.""" + from services.file_service import get_config_path + config_file = get_config_path(_CONFIG_FILENAME) + + try: + config_file.parent.mkdir(exist_ok=True) + with open(str(config_file), "w", encoding="utf-8") as f: + json.dump(data, f, ensure_ascii=False, indent=2) + logger.info("Config saved to %s", config_file) + except OSError as exc: + logger.error("Failed to save config to %s: %s", config_file, exc) diff --git a/tasks.md b/tasks.md index 7257413..20179c1 100644 --- a/tasks.md +++ b/tasks.md @@ -109,18 +109,18 @@ 任务: -- [ ] 先读取 `src/services/config_service.py` 现有内容 -- [ ] 完善 `src/services/config_service.py` -- [ ] 定义默认配置 -- [ ] 支持读取 JSON 配置 -- [ ] 支持保存 JSON 配置 -- [ ] 配置损坏时使用安全默认值并记录日志 +- [x] 先读取 `src/services/config_service.py` 现有内容 +- [x] 完善 `src/services/config_service.py` +- [x] 定义默认配置 +- [x] 支持读取 JSON 配置 +- [x] 支持保存 JSON 配置 +- [x] 配置损坏时使用安全默认值并记录日志 验收: -- [ ] 缺少配置文件时程序可启动 -- [ ] 配置文件损坏时程序可启动并记录日志 -- [ ] 不会无提示清空用户配置 +- [x] 缺少配置文件时程序可启动 +- [x] 配置文件损坏时程序可启动并记录日志 +- [x] 不会无提示清空用户配置 ## 2. 核心数据模型