Files
playwrite/gui/config_manager.py
Misaka_Company 71621dc8a0 feat: add Tkinter GUI application for ERP automation tools
Implement a comprehensive GUI application with the following features:
- Data Extraction tab: Extract material plan data from ERP system
- Material Validation tab: Validate material status and match deletions
- Data Query tab: Query database for production order information
- Settings tab: Manage ERP, database, browser, and path configurations

Key components:
- MainWindow: Tabbed interface with status bar
- ConfigManager: JSON-based configuration management
- LogText: Custom read-only text widget with colored logging
- FileSelector: Reusable file/directory selection component
- ProgressDialog: Modal progress dialog for long operations

Technical details:
- Thread-safe UI updates using root.after()
- Stdout capture for legacy script integration
- Event-based readonly mode allowing copy/select operations
- Custom widget composition to avoid Tkinter ScrolledText issues

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-05 13:33:23 +08:00

142 lines
3.7 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
配置管理器
负责加载、保存和管理用户配置。
"""
import json
import os
from typing import Any, Dict
from config.user_settings import DEFAULT_SETTINGS
class ConfigManager:
"""配置管理器"""
def __init__(self, config_file: str = "config/user_settings.json"):
"""
初始化配置管理器
Args:
config_file: 配置文件路径
"""
self.config_file = config_file
self.settings = self.load()
def load(self) -> Dict[str, Any]:
"""
加载配置文件
Returns:
配置字典,如果文件不存在则返回默认配置
"""
if os.path.exists(self.config_file):
try:
with open(self.config_file, 'r', encoding='utf-8') as f:
loaded_settings = json.load(f)
# 合并默认配置,确保所有必需的键都存在
return self._merge_settings(DEFAULT_SETTINGS, loaded_settings)
except (json.JSONDecodeError, IOError) as e:
print(f"加载配置文件失败: {e}")
return DEFAULT_SETTINGS.copy()
else:
# 首次运行,创建默认配置文件
self.save(DEFAULT_SETTINGS.copy())
return DEFAULT_SETTINGS.copy()
def save(self, settings: Dict[str, Any] = None) -> bool:
"""
保存配置到文件
Args:
settings: 要保存的配置字典,如果为 None 则保存当前配置
Returns:
保存是否成功
"""
if settings is not None:
self.settings = settings
try:
# 确保配置目录存在
os.makedirs(os.path.dirname(self.config_file), exist_ok=True)
with open(self.config_file, 'w', encoding='utf-8') as f:
json.dump(self.settings, f, ensure_ascii=False, indent=2)
return True
except IOError as e:
print(f"保存配置文件失败: {e}")
return False
def get(self, key: str, default=None) -> Any:
"""
获取配置项
支持点号分隔的路径,如 "erp.url"
Args:
key: 配置键
default: 默认值
Returns:
配置值
"""
keys = key.split('.')
value = self.settings
for k in keys:
if isinstance(value, dict) and k in value:
value = value[k]
else:
return default
return value
def set(self, key: str, value: Any) -> None:
"""
设置配置项
支持点号分隔的路径,如 "erp.url"
Args:
key: 配置键
value: 配置值
"""
keys = key.split('.')
settings = self.settings
for k in keys[:-1]:
if k not in settings:
settings[k] = {}
settings = settings[k]
settings[keys[-1]] = value
def reset_to_defaults(self) -> None:
"""重置为默认配置"""
self.settings = DEFAULT_SETTINGS.copy()
self.save()
def _merge_settings(self, defaults: Dict, loaded: Dict) -> Dict:
"""
合并默认配置和加载的配置
Args:
defaults: 默认配置
loaded: 加载的配置
Returns:
合并后的配置
"""
result = defaults.copy()
for key, value in loaded.items():
if key in result and isinstance(result[key], dict) and isinstance(value, dict):
result[key] = self._merge_settings(result[key], value)
else:
result[key] = value
return result