🎨 Refactor config service
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -14,32 +16,9 @@ const (
|
||||
TabTypeTab TabType = "tab"
|
||||
)
|
||||
|
||||
// EncodingType 定义文件编码格式类型
|
||||
type EncodingType string
|
||||
|
||||
const (
|
||||
// EncodingUTF8 UTF-8编码
|
||||
EncodingUTF8 EncodingType = "UTF-8"
|
||||
// EncodingUTF8BOM UTF-8带BOM编码
|
||||
EncodingUTF8BOM EncodingType = "UTF-8-BOM"
|
||||
// EncodingUTF16LE UTF-16小端编码
|
||||
EncodingUTF16LE EncodingType = "UTF-16 LE"
|
||||
// EncodingUTF16BE UTF-16大端编码
|
||||
EncodingUTF16BE EncodingType = "UTF-16 BE"
|
||||
// EncodingISO88591 ISO-8859-1编码
|
||||
EncodingISO88591 EncodingType = "ISO-8859-1"
|
||||
// EncodingGB18030 GB18030编码
|
||||
EncodingGB18030 EncodingType = "GB18030"
|
||||
// EncodingGBK GBK编码
|
||||
EncodingGBK EncodingType = "GBK"
|
||||
// EncodingBig5 Big5编码
|
||||
EncodingBig5 EncodingType = "Big5"
|
||||
)
|
||||
|
||||
// EditorConfig 定义编辑器配置
|
||||
type EditorConfig struct {
|
||||
FontSize int `json:"fontSize"` // 字体大小
|
||||
Encoding EncodingType `json:"encoding"` // 文件保存的编码
|
||||
EnableTabIndent bool `json:"enableTabIndent"` // 是否启用Tab缩进
|
||||
TabSize int `json:"tabSize"` // Tab大小
|
||||
TabType TabType `json:"tabType"` // Tab类型(空格或Tab)
|
||||
@@ -56,16 +35,17 @@ const (
|
||||
LangEnUS LanguageType = "en-US"
|
||||
)
|
||||
|
||||
// PathConfig 定义配置文件路径相关配置
|
||||
type PathConfig struct {
|
||||
RootDir string `json:"rootDir"` // 根目录
|
||||
// PathsConfig 路径配置集合
|
||||
type PathsConfig struct {
|
||||
ConfigPath string `json:"configPath"` // 配置文件路径
|
||||
LogPath string `json:"logPath"` // 日志文件路径
|
||||
DataPath string `json:"dataPath"` // 数据存储路径
|
||||
}
|
||||
|
||||
// AppConfig 应用配置
|
||||
// AppConfig 应用配置 - 包含业务配置和路径配置
|
||||
type AppConfig struct {
|
||||
Editor EditorConfig `json:"editor"` // 编辑器配置
|
||||
Paths PathConfig `json:"paths"` // 路径配置
|
||||
Paths PathsConfig `json:"paths"` // 路径配置
|
||||
Metadata ConfigMetadata `json:"metadata"` // 配置元数据
|
||||
}
|
||||
|
||||
@@ -77,18 +57,27 @@ type ConfigMetadata struct {
|
||||
|
||||
// NewDefaultAppConfig 创建默认应用配置
|
||||
func NewDefaultAppConfig() *AppConfig {
|
||||
// 获取用户主目录
|
||||
homePath, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
homePath = "."
|
||||
}
|
||||
|
||||
// 默认路径配置
|
||||
rootDir := filepath.Join(homePath, ".voidraft")
|
||||
|
||||
return &AppConfig{
|
||||
Editor: EditorConfig{
|
||||
FontSize: 13,
|
||||
Encoding: EncodingUTF8,
|
||||
EnableTabIndent: true,
|
||||
TabSize: 4,
|
||||
TabType: TabTypeSpaces,
|
||||
Language: LangZhCN,
|
||||
},
|
||||
Paths: PathConfig{
|
||||
RootDir: ".voidraft",
|
||||
ConfigPath: "config/config.json",
|
||||
Paths: PathsConfig{
|
||||
ConfigPath: filepath.Join(rootDir, "config", "config.json"),
|
||||
LogPath: filepath.Join(rootDir, "logs"),
|
||||
DataPath: filepath.Join(rootDir, "data"),
|
||||
},
|
||||
Metadata: ConfigMetadata{
|
||||
Version: "1.0.0",
|
||||
|
93
internal/services/config/config_locator.go
Normal file
93
internal/services/config/config_locator.go
Normal file
@@ -0,0 +1,93 @@
|
||||
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
|
||||
}
|
302
internal/services/config/config_service.go
Normal file
302
internal/services/config/config_service.go
Normal file
@@ -0,0 +1,302 @@
|
||||
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()
|
||||
}
|
117
internal/services/config/config_storage.go
Normal file
117
internal/services/config/config_storage.go
Normal file
@@ -0,0 +1,117 @@
|
||||
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
|
||||
}
|
@@ -1,228 +0,0 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
"voidraft/internal/models"
|
||||
|
||||
"github.com/wailsapp/wails/v3/pkg/services/log"
|
||||
)
|
||||
|
||||
// ConfigService 提供配置管理功能
|
||||
type ConfigService struct {
|
||||
store *Store[models.AppConfig]
|
||||
homePath string
|
||||
configPath string
|
||||
logger *log.LoggerService
|
||||
}
|
||||
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 = "."
|
||||
}
|
||||
|
||||
// 创建默认配置
|
||||
defaultConfig := models.NewDefaultAppConfig()
|
||||
|
||||
// 构建完整的配置文件路径
|
||||
configFilePath := filepath.Join(homePath, defaultConfig.Paths.RootDir, defaultConfig.Paths.ConfigPath)
|
||||
|
||||
// 创建Store选项
|
||||
storeOption := StoreOption{
|
||||
FilePath: configFilePath,
|
||||
AutoSave: true,
|
||||
Logger: logger,
|
||||
}
|
||||
|
||||
// 创建存储服务
|
||||
store := NewStore[models.AppConfig](storeOption)
|
||||
|
||||
// 构造配置服务实例
|
||||
service := &ConfigService{
|
||||
store: store,
|
||||
homePath: homePath,
|
||||
configPath: configFilePath,
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
// 检查是否需要设置默认配置
|
||||
config := store.Get()
|
||||
if isEmptyConfig(config) {
|
||||
err := store.Set(*defaultConfig)
|
||||
if err != nil {
|
||||
logger.Error("Config: Failed to set default config", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
return service
|
||||
}
|
||||
|
||||
// isEmptyConfig 检查配置是否为空
|
||||
func isEmptyConfig(config models.AppConfig) bool {
|
||||
// 检查基本字段
|
||||
if config.Editor.FontSize == 0 && config.Paths.RootDir == "" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetConfig 获取完整应用配置
|
||||
func (cs *ConfigService) GetConfig() (*models.AppConfig, error) {
|
||||
config := cs.store.Get()
|
||||
|
||||
// 如果配置为空,返回默认配置
|
||||
if isEmptyConfig(config) {
|
||||
defaultConfig := models.NewDefaultAppConfig()
|
||||
if err := cs.store.Set(*defaultConfig); err != nil {
|
||||
cs.logger.Error("Config: Failed to save default config", "error", err)
|
||||
}
|
||||
return defaultConfig, nil
|
||||
}
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
// SaveConfig 保存完整应用配置
|
||||
func (cs *ConfigService) SaveConfig(config *models.AppConfig) error {
|
||||
// 更新配置元数据
|
||||
config.Metadata.LastUpdated = time.Now()
|
||||
|
||||
return cs.store.Set(*config)
|
||||
}
|
||||
|
||||
// ResetConfig 重置为默认配置
|
||||
func (cs *ConfigService) ResetConfig() error {
|
||||
defaultConfig := models.NewDefaultAppConfig()
|
||||
|
||||
err := cs.store.Set(*defaultConfig)
|
||||
if err != nil {
|
||||
cs.logger.Error("Config: Failed to save default config", "error", err)
|
||||
return fmt.Errorf("failed to reset config: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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
|
||||
config.Metadata.LastUpdated = time.Now()
|
||||
|
||||
// 保存更新后的配置
|
||||
return cs.store.Set(*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
|
||||
config.Metadata.LastUpdated = time.Now()
|
||||
|
||||
// 保存更新后的配置
|
||||
return cs.store.Set(*config)
|
||||
}
|
||||
|
||||
// GetPathConfig 获取路径配置
|
||||
func (cs *ConfigService) GetPathConfig() (models.PathConfig, error) {
|
||||
config, err := cs.GetConfig()
|
||||
if err != nil {
|
||||
return models.PathConfig{}, err
|
||||
}
|
||||
return config.Paths, nil
|
||||
}
|
||||
|
||||
// UpdatePathConfig 更新路径配置
|
||||
func (cs *ConfigService) UpdatePathConfig(pathConfig models.PathConfig) error {
|
||||
// 获取当前配置
|
||||
config, err := cs.GetConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 更新路径配置
|
||||
config.Paths = pathConfig
|
||||
config.Metadata.LastUpdated = time.Now()
|
||||
|
||||
// 保存更新后的配置
|
||||
return cs.store.Set(*config)
|
||||
}
|
||||
|
||||
// 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
|
||||
config.Metadata.LastUpdated = time.Now()
|
||||
|
||||
// 保存更新后的配置
|
||||
return cs.store.Set(*config)
|
||||
}
|
||||
|
||||
// OnShutdown 服务关闭时调用
|
||||
func (cs *ConfigService) OnShutdown() error {
|
||||
// 如果有未保存的更改,保存数据
|
||||
if cs.store.HasUnsavedChanges() {
|
||||
return cs.store.Save()
|
||||
}
|
||||
return nil
|
||||
}
|
@@ -2,17 +2,18 @@ package services
|
||||
|
||||
import (
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
"voidraft/internal/services/config"
|
||||
)
|
||||
|
||||
// ServiceManager 服务管理器,负责协调各个服务
|
||||
type ServiceManager struct {
|
||||
configService *ConfigService
|
||||
configService *config.ConfigService
|
||||
}
|
||||
|
||||
// NewServiceManager 创建新的服务管理器实例
|
||||
func NewServiceManager() *ServiceManager {
|
||||
// 初始化配置服务
|
||||
configService := NewConfigService()
|
||||
configService := config.NewConfigService()
|
||||
|
||||
return &ServiceManager{
|
||||
configService: configService,
|
||||
@@ -27,6 +28,6 @@ func (sm *ServiceManager) GetServices() []application.Service {
|
||||
}
|
||||
|
||||
// GetConfigService 获取配置服务实例
|
||||
func (sm *ServiceManager) GetConfigService() *ConfigService {
|
||||
func (sm *ServiceManager) GetConfigService() *config.ConfigService {
|
||||
return sm.configService
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package services
|
||||
package store
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -125,10 +125,10 @@ func (s *Store[T]) saveInternal() error {
|
||||
}
|
||||
tempFilePath := tempFile.Name()
|
||||
defer func() {
|
||||
tempFile.Close()
|
||||
_ = tempFile.Close()
|
||||
// 如果出错,删除临时文件
|
||||
if err != nil {
|
||||
os.Remove(tempFilePath)
|
||||
_ = os.Remove(tempFilePath)
|
||||
}
|
||||
}()
|
||||
|
Reference in New Issue
Block a user