303 lines
7.4 KiB
Go
303 lines
7.4 KiB
Go
package config
|
||
|
||
import (
|
||
"fmt"
|
||
"os"
|
||
"path/filepath"
|
||
"sync"
|
||
"time"
|
||
"voidraft/internal/models"
|
||
|
||
"github.com/wailsapp/wails/v3/pkg/services/log"
|
||
)
|
||
|
||
// ConfigService 提供配置管理功能
|
||
type ConfigService struct {
|
||
storage ConfigStorage // 配置存储接口
|
||
locator ConfigLocator // 配置定位器接口
|
||
logger *log.LoggerService
|
||
cache *models.AppConfig // 配置缓存
|
||
cacheMu sync.RWMutex // 缓存锁
|
||
}
|
||
|
||
type Service struct{}
|
||
|
||
// NewConfigService 创建新的配置服务实例
|
||
func NewConfigService() *ConfigService {
|
||
// 初始化日志服务
|
||
logger := log.New()
|
||
|
||
// 获取用户主目录
|
||
homePath, err := os.UserHomeDir()
|
||
if err != nil {
|
||
logger.Error("Config: Failed to get user home directory", "error", err)
|
||
homePath = "."
|
||
}
|
||
|
||
// 获取默认配置路径
|
||
defaultPath := GetDefaultConfigPath()
|
||
|
||
// 创建配置定位器
|
||
locationFile := filepath.Join(homePath, ".voidraft", "config.location")
|
||
locator := NewFileConfigLocator(locationFile, defaultPath, logger)
|
||
|
||
// 获取实际配置路径
|
||
configPath := locator.GetConfigPath()
|
||
logger.Info("Config: Using config path", "path", configPath)
|
||
|
||
// 创建配置存储
|
||
storage := NewFileConfigStorage(configPath, logger)
|
||
|
||
// 构造配置服务实例
|
||
service := &ConfigService{
|
||
storage: storage,
|
||
locator: locator,
|
||
logger: logger,
|
||
}
|
||
|
||
// 初始化加载配置
|
||
service.loadInitialConfig()
|
||
|
||
return service
|
||
}
|
||
|
||
// loadInitialConfig 加载初始配置
|
||
func (cs *ConfigService) loadInitialConfig() {
|
||
// 尝试加载配置
|
||
config, err := cs.storage.Load()
|
||
if err != nil {
|
||
// 如果加载失败,使用默认配置
|
||
defaultConfig := models.NewDefaultAppConfig()
|
||
defaultConfig.Paths.ConfigPath = cs.storage.GetPath()
|
||
|
||
// 保存默认配置
|
||
if err := cs.storage.Save(*defaultConfig); err != nil {
|
||
cs.logger.Error("Config: Failed to save default config", "error", err)
|
||
} else {
|
||
// 更新缓存
|
||
cs.cacheMu.Lock()
|
||
cs.cache = defaultConfig
|
||
cs.cacheMu.Unlock()
|
||
}
|
||
} else {
|
||
// 确保配置中的路径与实际使用的路径一致
|
||
if config.Paths.ConfigPath != cs.storage.GetPath() {
|
||
config.Paths.ConfigPath = cs.storage.GetPath()
|
||
if err := cs.storage.Save(config); err != nil {
|
||
cs.logger.Error("Config: Failed to sync config path", "error", err)
|
||
}
|
||
}
|
||
|
||
// 更新缓存
|
||
cs.cacheMu.Lock()
|
||
cs.cache = &config
|
||
cs.cacheMu.Unlock()
|
||
}
|
||
}
|
||
|
||
// GetConfig 获取完整应用配置
|
||
func (cs *ConfigService) GetConfig() (*models.AppConfig, error) {
|
||
// 优先使用缓存
|
||
cs.cacheMu.RLock()
|
||
if cs.cache != nil {
|
||
config := *cs.cache
|
||
cs.cacheMu.RUnlock()
|
||
return &config, nil
|
||
}
|
||
cs.cacheMu.RUnlock()
|
||
|
||
// 缓存不存在,从存储加载
|
||
config, err := cs.storage.Load()
|
||
if err != nil {
|
||
// 加载失败,使用默认配置
|
||
defaultConfig := models.NewDefaultAppConfig()
|
||
defaultConfig.Paths.ConfigPath = cs.storage.GetPath()
|
||
|
||
// 保存默认配置
|
||
if saveErr := cs.storage.Save(*defaultConfig); saveErr != nil {
|
||
cs.logger.Error("Config: Failed to save default config", "error", saveErr)
|
||
}
|
||
|
||
// 更新缓存
|
||
cs.cacheMu.Lock()
|
||
cs.cache = defaultConfig
|
||
cs.cacheMu.Unlock()
|
||
|
||
return defaultConfig, nil
|
||
}
|
||
|
||
// 更新缓存
|
||
cs.cacheMu.Lock()
|
||
cs.cache = &config
|
||
cs.cacheMu.Unlock()
|
||
|
||
return &config, nil
|
||
}
|
||
|
||
// SaveConfig 保存完整应用配置
|
||
func (cs *ConfigService) SaveConfig(config *models.AppConfig) error {
|
||
// 更新配置元数据
|
||
config.Metadata.LastUpdated = time.Now()
|
||
|
||
// 确保ConfigPath与当前路径一致
|
||
config.Paths.ConfigPath = cs.storage.GetPath()
|
||
|
||
// 更新缓存
|
||
cs.cacheMu.Lock()
|
||
cs.cache = config
|
||
cs.cacheMu.Unlock()
|
||
|
||
// 保存到存储
|
||
return cs.storage.Save(*config)
|
||
}
|
||
|
||
// UpdateConfigPath 更新配置文件路径
|
||
func (cs *ConfigService) UpdateConfigPath(newPath string) error {
|
||
// 如果路径相同,无需更改
|
||
if newPath == cs.storage.GetPath() {
|
||
return nil
|
||
}
|
||
|
||
// 获取当前配置(优先使用缓存)
|
||
config, err := cs.GetConfig()
|
||
if err != nil {
|
||
return fmt.Errorf("failed to get current config: %w", err)
|
||
}
|
||
|
||
// 更新配置中的路径
|
||
config.Paths.ConfigPath = newPath
|
||
|
||
// 移动到新路径
|
||
if err := cs.storage.MoveTo(newPath, *config); err != nil {
|
||
return fmt.Errorf("failed to move config to new path: %w", err)
|
||
}
|
||
|
||
// 更新定位器
|
||
if err := cs.locator.SetConfigPath(newPath); err != nil {
|
||
cs.logger.Error("Config: Failed to update location file", "error", err)
|
||
// 继续执行,这不是致命错误
|
||
}
|
||
|
||
cs.logger.Info("Config: Config path updated", "path", newPath)
|
||
|
||
return nil
|
||
}
|
||
|
||
// UpdatePaths 更新路径配置
|
||
func (cs *ConfigService) UpdatePaths(paths models.PathsConfig) error {
|
||
config, err := cs.GetConfig()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 检查配置文件路径是否变更
|
||
if paths.ConfigPath != "" && paths.ConfigPath != cs.storage.GetPath() {
|
||
// 如果配置路径有变化,使用专门的方法处理
|
||
if err := cs.UpdateConfigPath(paths.ConfigPath); err != nil {
|
||
return fmt.Errorf("failed to update config path: %w", err)
|
||
}
|
||
// 更新后重新加载配置
|
||
config, err = cs.GetConfig()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
// 更新其他路径,但保持ConfigPath不变
|
||
config.Paths.LogPath = paths.LogPath
|
||
config.Paths.DataPath = paths.DataPath
|
||
|
||
// 确保ConfigPath与当前一致
|
||
config.Paths.ConfigPath = cs.storage.GetPath()
|
||
|
||
return cs.SaveConfig(config)
|
||
}
|
||
|
||
// ResetConfig 重置为默认配置
|
||
func (cs *ConfigService) ResetConfig() error {
|
||
defaultConfig := models.NewDefaultAppConfig()
|
||
// 保留当前配置路径
|
||
defaultConfig.Paths.ConfigPath = cs.storage.GetPath()
|
||
|
||
return cs.SaveConfig(defaultConfig)
|
||
}
|
||
|
||
// GetEditorConfig 获取编辑器配置
|
||
func (cs *ConfigService) GetEditorConfig() (models.EditorConfig, error) {
|
||
config, err := cs.GetConfig()
|
||
if err != nil {
|
||
return models.EditorConfig{}, err
|
||
}
|
||
return config.Editor, nil
|
||
}
|
||
|
||
// UpdateEditorConfig 更新编辑器配置
|
||
func (cs *ConfigService) UpdateEditorConfig(editorConfig models.EditorConfig) error {
|
||
config, err := cs.GetConfig()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
config.Editor = editorConfig
|
||
return cs.SaveConfig(config)
|
||
}
|
||
|
||
// GetLanguage 获取当前语言设置
|
||
func (cs *ConfigService) GetLanguage() (models.LanguageType, error) {
|
||
editorConfig, err := cs.GetEditorConfig()
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
return editorConfig.Language, nil
|
||
}
|
||
|
||
// SetLanguage 设置语言
|
||
func (cs *ConfigService) SetLanguage(language models.LanguageType) error {
|
||
// 验证语言类型有效
|
||
if language != models.LangZhCN && language != models.LangEnUS {
|
||
return fmt.Errorf("unsupported language: %s", language)
|
||
}
|
||
|
||
config, err := cs.GetConfig()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
config.Editor.Language = language
|
||
return cs.SaveConfig(config)
|
||
}
|
||
|
||
// GetPaths 获取路径配置
|
||
func (cs *ConfigService) GetPaths() (models.PathsConfig, error) {
|
||
config, err := cs.GetConfig()
|
||
if err != nil {
|
||
return models.PathsConfig{}, err
|
||
}
|
||
return config.Paths, nil
|
||
}
|
||
|
||
// GetMetadata 获取配置元数据
|
||
func (cs *ConfigService) GetMetadata() (models.ConfigMetadata, error) {
|
||
config, err := cs.GetConfig()
|
||
if err != nil {
|
||
return models.ConfigMetadata{}, err
|
||
}
|
||
return config.Metadata, nil
|
||
}
|
||
|
||
// UpdateMetadata 更新配置元数据
|
||
func (cs *ConfigService) UpdateMetadata(metadata models.ConfigMetadata) error {
|
||
config, err := cs.GetConfig()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
config.Metadata = metadata
|
||
return cs.SaveConfig(config)
|
||
}
|
||
|
||
// GetConfigPath 获取当前配置文件路径
|
||
func (cs *ConfigService) GetConfigPath() string {
|
||
return cs.storage.GetPath()
|
||
}
|