🎨 Optimize configuration service

This commit is contained in:
2025-05-12 20:52:33 +08:00
parent c0db3a68cd
commit 7e6e7e4e73
11 changed files with 66 additions and 356 deletions

View File

@@ -38,9 +38,8 @@ const (
// PathsConfig 路径配置集合
type PathsConfig struct {
ConfigPath string `json:"configPath"` // 配置文件路径
LogPath string `json:"logPath"` // 日志文件路径
DataPath string `json:"dataPath"` // 数据存储路径
LogPath string `json:"logPath"` // 日志文件路径
DataPath string `json:"dataPath"` // 数据存储路径
}
// AppConfig 应用配置 - 包含业务配置和路径配置
@@ -77,9 +76,8 @@ func NewDefaultAppConfig() *AppConfig {
AlwaysOnTop: false,
},
Paths: PathsConfig{
ConfigPath: filepath.Join(rootDir, "config", "config.json"),
LogPath: filepath.Join(rootDir, "logs"),
DataPath: filepath.Join(rootDir, "data"),
LogPath: filepath.Join(rootDir, "logs"),
DataPath: filepath.Join(rootDir, "data"),
},
Metadata: ConfigMetadata{
Version: "1.0.0",

View File

@@ -1,93 +0,0 @@
package config
import (
"fmt"
"os"
"path/filepath"
"sync"
"github.com/wailsapp/wails/v3/pkg/services/log"
)
// ConfigLocator 配置定位器接口
type ConfigLocator interface {
// GetConfigPath 获取配置文件路径
GetConfigPath() string
// SetConfigPath 设置配置文件路径
SetConfigPath(string) error
}
// FileConfigLocator 基于文件的配置定位器
type FileConfigLocator struct {
locationFile string
defaultPath string
logger *log.LoggerService
mu sync.RWMutex
}
// NewFileConfigLocator 创建文件配置定位器
func NewFileConfigLocator(locationFile, defaultPath string, logger *log.LoggerService) *FileConfigLocator {
if logger == nil {
logger = log.New()
}
return &FileConfigLocator{
locationFile: locationFile,
defaultPath: defaultPath,
logger: logger,
}
}
// GetDefaultConfigPath 获取默认配置路径
func GetDefaultConfigPath() string {
homePath, err := os.UserHomeDir()
if err != nil {
return filepath.Join(".voidraft", "config", "config.json")
}
return filepath.Join(homePath, ".voidraft", "config", "config.json")
}
// GetConfigPath 获取配置文件路径
func (fcl *FileConfigLocator) GetConfigPath() string {
fcl.mu.RLock()
defer fcl.mu.RUnlock()
// 尝试从位置文件读取
if _, err := os.Stat(fcl.locationFile); err == nil {
if data, err := os.ReadFile(fcl.locationFile); err == nil && len(data) > 0 {
path := string(data)
// 验证路径目录是否存在
if _, err := os.Stat(filepath.Dir(path)); err == nil {
fcl.logger.Info("ConfigLocator: Using stored path", "path", path)
return path
}
fcl.logger.Error("ConfigLocator: Stored path invalid, using default", "path", path)
}
}
// 返回默认路径
fcl.logger.Info("ConfigLocator: Using default path", "path", fcl.defaultPath)
return fcl.defaultPath
}
// SetConfigPath 设置配置文件路径
func (fcl *FileConfigLocator) SetConfigPath(path string) error {
fcl.mu.Lock()
defer fcl.mu.Unlock()
// 确保位置文件目录存在
if err := os.MkdirAll(filepath.Dir(fcl.locationFile), 0755); err != nil {
return fmt.Errorf("failed to create location directory: %w", err)
}
// 写入位置文件
if err := os.WriteFile(fcl.locationFile, []byte(path), 0644); err != nil {
return fmt.Errorf("failed to write location file: %w", err)
}
fcl.logger.Info("ConfigLocator: Updated config path", "path", path)
return nil
}

View File

@@ -1,117 +0,0 @@
package config
import (
"fmt"
"os"
"path/filepath"
"sync"
"voidraft/internal/models"
"voidraft/internal/services/store"
"github.com/wailsapp/wails/v3/pkg/services/log"
)
// ConfigStorage 配置存储接口
type ConfigStorage interface {
// Load 加载配置
Load() (models.AppConfig, error)
// Save 保存配置
Save(models.AppConfig) error
// GetPath 获取存储路径
GetPath() string
// MoveTo 移动到新路径
MoveTo(string, models.AppConfig) error
}
// FileConfigStorage 基于文件的配置存储
type FileConfigStorage struct {
store *store.Store[models.AppConfig]
currentPath string
logger *log.LoggerService
mu sync.RWMutex
}
// NewFileConfigStorage 创建文件配置存储
func NewFileConfigStorage(path string, logger *log.LoggerService) *FileConfigStorage {
if logger == nil {
logger = log.New()
}
return &FileConfigStorage{
store: store.NewStore[models.AppConfig](store.StoreOption{
FilePath: path,
AutoSave: true,
Logger: logger,
}),
currentPath: path,
logger: logger,
}
}
// Load 加载配置
func (fcs *FileConfigStorage) Load() (models.AppConfig, error) {
fcs.mu.RLock()
defer fcs.mu.RUnlock()
config := fcs.store.Get()
// 检查配置是否为空
if isEmptyConfig(config) {
return models.AppConfig{}, fmt.Errorf("empty config detected")
}
return config, nil
}
// Save 保存配置
func (fcs *FileConfigStorage) Save(config models.AppConfig) error {
fcs.mu.Lock()
defer fcs.mu.Unlock()
return fcs.store.Set(config)
}
// GetPath 获取存储路径
func (fcs *FileConfigStorage) GetPath() string {
fcs.mu.RLock()
defer fcs.mu.RUnlock()
return fcs.currentPath
}
// MoveTo 移动到新路径
func (fcs *FileConfigStorage) MoveTo(newPath string, config models.AppConfig) error {
fcs.mu.Lock()
defer fcs.mu.Unlock()
// 创建目录
if err := os.MkdirAll(filepath.Dir(newPath), 0755); err != nil {
return fmt.Errorf("failed to create directory: %w", err)
}
// 创建新存储
newStore := store.NewStore[models.AppConfig](store.StoreOption{
FilePath: newPath,
AutoSave: true,
Logger: fcs.logger,
})
// 保存到新位置
if err := newStore.Set(config); err != nil {
return fmt.Errorf("failed to save config to new path: %w", err)
}
// 更新状态
fcs.store = newStore
fcs.currentPath = newPath
return nil
}
// isEmptyConfig 检查配置是否为空
func isEmptyConfig(config models.AppConfig) bool {
return config.Editor.FontSize == 0
}

View File

@@ -1,27 +1,24 @@
package config
package services
import (
"fmt"
"github.com/wailsapp/wails/v3/pkg/services/log"
"os"
"path/filepath"
"sync"
"time"
"voidraft/internal/models"
"github.com/wailsapp/wails/v3/pkg/services/log"
)
// ConfigService 提供配置管理功能
type ConfigService struct {
storage ConfigStorage // 配置存储接口
locator ConfigLocator // 配置定位器接口
store *Store[models.AppConfig] // 配置存储
path string // 配置文件路径
logger *log.LoggerService
cache *models.AppConfig // 配置缓存
cacheMu sync.RWMutex // 缓存锁
}
type Service struct{}
// NewConfigService 创建新的配置服务实例
func NewConfigService() *ConfigService {
// 初始化日志服务
@@ -34,25 +31,22 @@ func NewConfigService() *ConfigService {
homePath = "."
}
// 获取默认配置路径
defaultPath := GetDefaultConfigPath()
// 创建配置定位器
locationFile := filepath.Join(homePath, ".voidraft", "config.location")
locator := NewFileConfigLocator(locationFile, defaultPath, logger)
// 获取实际配置路径
configPath := locator.GetConfigPath()
// 固定配置路径
configPath := filepath.Join(homePath, ".voidraft", "config", "config.json")
logger.Info("Config: Using config path", "path", configPath)
// 创建配置存储
storage := NewFileConfigStorage(configPath, logger)
// 创建存储
store := NewStore[models.AppConfig](StoreOption{
FilePath: configPath,
AutoSave: true,
Logger: logger,
})
// 构造配置服务实例
service := &ConfigService{
storage: storage,
locator: locator,
logger: logger,
store: store,
path: configPath,
logger: logger,
}
// 初始化加载配置
@@ -64,14 +58,13 @@ func NewConfigService() *ConfigService {
// loadInitialConfig 加载初始配置
func (cs *ConfigService) loadInitialConfig() {
// 尝试加载配置
config, err := cs.storage.Load()
config, err := cs.load()
if err != nil {
// 如果加载失败,使用默认配置
defaultConfig := models.NewDefaultAppConfig()
defaultConfig.Paths.ConfigPath = cs.storage.GetPath()
// 保存默认配置
if err := cs.storage.Save(*defaultConfig); err != nil {
if err := cs.save(*defaultConfig); err != nil {
cs.logger.Error("Config: Failed to save default config", "error", err)
} else {
// 更新缓存
@@ -80,14 +73,6 @@ func (cs *ConfigService) loadInitialConfig() {
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
@@ -95,6 +80,28 @@ func (cs *ConfigService) loadInitialConfig() {
}
}
// load 加载配置
func (cs *ConfigService) load() (models.AppConfig, error) {
config := cs.store.Get()
// 检查配置是否为空
if isEmptyConfig(config) {
return models.AppConfig{}, fmt.Errorf("empty config detected")
}
return config, nil
}
// save 保存配置
func (cs *ConfigService) save(config models.AppConfig) error {
return cs.store.Set(config)
}
// isEmptyConfig 检查配置是否为空
func isEmptyConfig(config models.AppConfig) bool {
return config.Editor.FontSize == 0
}
// GetConfig 获取完整应用配置
func (cs *ConfigService) GetConfig() (*models.AppConfig, error) {
// 优先使用缓存
@@ -107,14 +114,13 @@ func (cs *ConfigService) GetConfig() (*models.AppConfig, error) {
cs.cacheMu.RUnlock()
// 缓存不存在,从存储加载
config, err := cs.storage.Load()
config, err := cs.load()
if err != nil {
// 加载失败,使用默认配置
defaultConfig := models.NewDefaultAppConfig()
defaultConfig.Paths.ConfigPath = cs.storage.GetPath()
// 保存默认配置
if saveErr := cs.storage.Save(*defaultConfig); saveErr != nil {
if saveErr := cs.save(*defaultConfig); saveErr != nil {
cs.logger.Error("Config: Failed to save default config", "error", saveErr)
}
@@ -139,48 +145,13 @@ 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
return cs.save(*config)
}
// UpdatePaths 更新路径配置
@@ -190,35 +161,16 @@ func (cs *ConfigService) UpdatePaths(paths models.PathsConfig) error {
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)
}
@@ -255,7 +207,7 @@ func (cs *ConfigService) GetLanguage() (models.LanguageType, error) {
func (cs *ConfigService) SetLanguage(language models.LanguageType) error {
// 验证语言类型有效
if language != models.LangZhCN && language != models.LangEnUS {
return fmt.Errorf("unsupported language: %s", language)
return nil
}
config, err := cs.GetConfig()
@@ -295,8 +247,3 @@ func (cs *ConfigService) UpdateMetadata(metadata models.ConfigMetadata) error {
config.Metadata = metadata
return cs.SaveConfig(config)
}
// GetConfigPath 获取当前配置文件路径
func (cs *ConfigService) GetConfigPath() string {
return cs.storage.GetPath()
}

View File

@@ -2,18 +2,17 @@ package services
import (
"github.com/wailsapp/wails/v3/pkg/application"
"voidraft/internal/services/config"
)
// ServiceManager 服务管理器,负责协调各个服务
type ServiceManager struct {
configService *config.ConfigService
configService *ConfigService
}
// NewServiceManager 创建新的服务管理器实例
func NewServiceManager() *ServiceManager {
// 初始化配置服务
configService := config.NewConfigService()
configService := NewConfigService()
return &ServiceManager{
configService: configService,
@@ -28,6 +27,6 @@ func (sm *ServiceManager) GetServices() []application.Service {
}
// GetConfigService 获取配置服务实例
func (sm *ServiceManager) GetConfigService() *config.ConfigService {
func (sm *ServiceManager) GetConfigService() *ConfigService {
return sm.configService
}

View File

@@ -1,4 +1,4 @@
package store
package services
import (
"encoding/json"