♻️ Refactor configuration service
This commit is contained in:
@@ -3,48 +3,22 @@ package services
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/wailsapp/wails/v3/pkg/services/log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
"voidraft/internal/models"
|
||||
|
||||
"dario.cat/mergo"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/wailsapp/wails/v3/pkg/services/log"
|
||||
)
|
||||
|
||||
// ConfigPath 配置路径提供接口
|
||||
type ConfigPath interface {
|
||||
// GetConfigPath 获取配置文件路径
|
||||
GetConfigPath() string
|
||||
}
|
||||
|
||||
// DefaultConfigPathProvider 默认配置路径提供者
|
||||
type DefaultConfigPathProvider struct{}
|
||||
|
||||
// GetConfigPath 获取默认配置路径
|
||||
func (p *DefaultConfigPathProvider) GetConfigPath() string {
|
||||
// 获取用户主目录
|
||||
homePath, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
homePath = "."
|
||||
}
|
||||
// 返回固定的配置路径
|
||||
return filepath.Join(homePath, ".voidraft", "config", "config.json")
|
||||
}
|
||||
|
||||
// ConfigOption 配置服务选项
|
||||
type ConfigOption struct {
|
||||
Logger *log.LoggerService // 日志服务
|
||||
PathProvider ConfigPath // 路径提供者
|
||||
}
|
||||
|
||||
// ConfigService 提供配置管理功能
|
||||
// ConfigService 提供基于 Viper 的配置管理功能
|
||||
type ConfigService struct {
|
||||
store *Store[models.AppConfig] // 配置存储
|
||||
logger *log.LoggerService // 日志服务
|
||||
cache *models.AppConfig // 配置缓存
|
||||
cacheMu sync.RWMutex // 缓存锁
|
||||
viper *viper.Viper // Viper 实例
|
||||
logger *log.LoggerService // 日志服务
|
||||
mu sync.RWMutex // 读写锁
|
||||
}
|
||||
|
||||
// ConfigError 配置错误
|
||||
@@ -65,280 +39,391 @@ func (e *ConfigError) Unwrap() error {
|
||||
|
||||
// Is 实现错误匹配
|
||||
func (e *ConfigError) Is(target error) bool {
|
||||
_, ok := target.(*ConfigError)
|
||||
var configError *ConfigError
|
||||
ok := errors.As(target, &configError)
|
||||
return ok
|
||||
}
|
||||
|
||||
// NewConfigService 创建新的配置服务实例
|
||||
func NewConfigService(opt ...ConfigOption) *ConfigService {
|
||||
var option ConfigOption
|
||||
// ConfigLimits 配置限制定义
|
||||
type ConfigLimits struct {
|
||||
FontSizeMin int
|
||||
FontSizeMax int
|
||||
TabSizeMin int
|
||||
TabSizeMax int
|
||||
}
|
||||
|
||||
// 使用第一个选项
|
||||
if len(opt) > 0 {
|
||||
option = opt[0]
|
||||
// getConfigLimits 获取配置限制
|
||||
func getConfigLimits() ConfigLimits {
|
||||
return ConfigLimits{
|
||||
FontSizeMin: 12,
|
||||
FontSizeMax: 28,
|
||||
TabSizeMin: 2,
|
||||
TabSizeMax: 8,
|
||||
}
|
||||
}
|
||||
|
||||
// validateAndFixValue 验证并修正配置值
|
||||
func (cs *ConfigService) validateAndFixValue(key string, value interface{}) (interface{}, bool) {
|
||||
limits := getConfigLimits()
|
||||
fixed := false
|
||||
|
||||
switch key {
|
||||
case "editor.font_size":
|
||||
if intVal, ok := value.(int); ok {
|
||||
if intVal < limits.FontSizeMin {
|
||||
cs.logger.Warning("Config: Font size too small, fixing", "original", intVal, "fixed", limits.FontSizeMin)
|
||||
return limits.FontSizeMin, true
|
||||
}
|
||||
if intVal > limits.FontSizeMax {
|
||||
cs.logger.Warning("Config: Font size too large, fixing", "original", intVal, "fixed", limits.FontSizeMax)
|
||||
return limits.FontSizeMax, true
|
||||
}
|
||||
}
|
||||
|
||||
case "editor.tab_size":
|
||||
if intVal, ok := value.(int); ok {
|
||||
if intVal < limits.TabSizeMin {
|
||||
cs.logger.Warning("Config: Tab size too small, fixing", "original", intVal, "fixed", limits.TabSizeMin)
|
||||
return limits.TabSizeMin, true
|
||||
}
|
||||
if intVal > limits.TabSizeMax {
|
||||
cs.logger.Warning("Config: Tab size too large, fixing", "original", intVal, "fixed", limits.TabSizeMax)
|
||||
return limits.TabSizeMax, true
|
||||
}
|
||||
}
|
||||
|
||||
case "editor.tab_type":
|
||||
if strVal, ok := value.(string); ok {
|
||||
validTypes := []string{string(models.TabTypeSpaces), string(models.TabTypeTab)}
|
||||
isValid := false
|
||||
for _, validType := range validTypes {
|
||||
if strVal == validType {
|
||||
isValid = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isValid {
|
||||
cs.logger.Warning("Config: Invalid tab type, fixing", "original", strVal, "fixed", string(models.TabTypeSpaces))
|
||||
return string(models.TabTypeSpaces), true
|
||||
}
|
||||
}
|
||||
|
||||
case "editor.language":
|
||||
if strVal, ok := value.(string); ok {
|
||||
validLanguages := []string{string(models.LangZhCN), string(models.LangEnUS)}
|
||||
isValid := false
|
||||
for _, validLang := range validLanguages {
|
||||
if strVal == validLang {
|
||||
isValid = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isValid {
|
||||
cs.logger.Warning("Config: Invalid language, fixing", "original", strVal, "fixed", string(models.LangZhCN))
|
||||
return string(models.LangZhCN), true
|
||||
}
|
||||
}
|
||||
|
||||
case "document.auto_save_delay":
|
||||
if intVal, ok := value.(int); ok {
|
||||
if intVal < 1000 {
|
||||
cs.logger.Warning("Config: Auto save delay too small, fixing", "original", intVal, "fixed", 1000)
|
||||
return 1000, true
|
||||
}
|
||||
if intVal > 30000 {
|
||||
cs.logger.Warning("Config: Auto save delay too large, fixing", "original", intVal, "fixed", 30000)
|
||||
return 30000, true
|
||||
}
|
||||
}
|
||||
|
||||
case "document.change_threshold":
|
||||
if intVal, ok := value.(int); ok {
|
||||
if intVal < 10 {
|
||||
cs.logger.Warning("Config: Change threshold too small, fixing", "original", intVal, "fixed", 10)
|
||||
return 10, true
|
||||
}
|
||||
if intVal > 10000 {
|
||||
cs.logger.Warning("Config: Change threshold too large, fixing", "original", intVal, "fixed", 10000)
|
||||
return 10000, true
|
||||
}
|
||||
}
|
||||
|
||||
case "document.min_save_interval":
|
||||
if intVal, ok := value.(int); ok {
|
||||
if intVal < 100 {
|
||||
cs.logger.Warning("Config: Min save interval too small, fixing", "original", intVal, "fixed", 100)
|
||||
return 100, true
|
||||
}
|
||||
if intVal > 10000 {
|
||||
cs.logger.Warning("Config: Min save interval too large, fixing", "original", intVal, "fixed", 10000)
|
||||
return 10000, true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value, fixed
|
||||
}
|
||||
|
||||
// validateAllConfig 验证并修正所有配置
|
||||
func (cs *ConfigService) validateAllConfig() error {
|
||||
hasChanges := false
|
||||
|
||||
// 获取当前配置
|
||||
var config models.AppConfig
|
||||
if err := cs.viper.Unmarshal(&config); err != nil {
|
||||
return &ConfigError{Operation: "unmarshal_for_validation", Err: err}
|
||||
}
|
||||
|
||||
// 验证编辑器配置
|
||||
if fixedValue, fixed := cs.validateAndFixValue("editor.font_size", config.Editor.FontSize); fixed {
|
||||
cs.viper.Set("editor.font_size", fixedValue)
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
if fixedValue, fixed := cs.validateAndFixValue("editor.tab_size", config.Editor.TabSize); fixed {
|
||||
cs.viper.Set("editor.tab_size", fixedValue)
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
if fixedValue, fixed := cs.validateAndFixValue("editor.tab_type", string(config.Editor.TabType)); fixed {
|
||||
cs.viper.Set("editor.tab_type", fixedValue)
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
if fixedValue, fixed := cs.validateAndFixValue("editor.language", string(config.Editor.Language)); fixed {
|
||||
cs.viper.Set("editor.language", fixedValue)
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
// 验证文档配置
|
||||
if fixedValue, fixed := cs.validateAndFixValue("document.auto_save_delay", config.Document.AutoSaveDelay); fixed {
|
||||
cs.viper.Set("document.auto_save_delay", fixedValue)
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
if fixedValue, fixed := cs.validateAndFixValue("document.change_threshold", config.Document.ChangeThreshold); fixed {
|
||||
cs.viper.Set("document.change_threshold", fixedValue)
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
if fixedValue, fixed := cs.validateAndFixValue("document.min_save_interval", config.Document.MinSaveInterval); fixed {
|
||||
cs.viper.Set("document.min_save_interval", fixedValue)
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
// 如果有修正,保存配置
|
||||
if hasChanges {
|
||||
if err := cs.viper.WriteConfig(); err != nil {
|
||||
return &ConfigError{Operation: "save_validated_config", Err: err}
|
||||
}
|
||||
cs.logger.Info("Config: Configuration validated and fixed")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewConfigService 创建新的配置服务实例
|
||||
func NewConfigService(logger *log.LoggerService) *ConfigService {
|
||||
// 设置日志服务
|
||||
logger := option.Logger
|
||||
if logger == nil {
|
||||
logger = log.New()
|
||||
}
|
||||
|
||||
// 设置路径提供者
|
||||
pathProvider := option.PathProvider
|
||||
if pathProvider == nil {
|
||||
pathProvider = &DefaultConfigPathProvider{}
|
||||
// 获取当前工作目录
|
||||
currentDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
currentDir = "."
|
||||
}
|
||||
|
||||
// 获取配置路径
|
||||
configPath := pathProvider.GetConfigPath()
|
||||
logger.Info("Config: Using config path", "path", configPath)
|
||||
// 固定配置路径和文件名
|
||||
configPath := filepath.Join(currentDir, "config")
|
||||
configName := "config"
|
||||
|
||||
// 创建存储
|
||||
store := NewStore[models.AppConfig](StoreOption{
|
||||
FilePath: configPath,
|
||||
Logger: logger,
|
||||
})
|
||||
// 创建 Viper 实例
|
||||
v := viper.New()
|
||||
|
||||
// 配置 Viper
|
||||
v.SetConfigName(configName)
|
||||
v.SetConfigType("yaml")
|
||||
v.AddConfigPath(configPath)
|
||||
|
||||
// 设置环境变量前缀
|
||||
v.SetEnvPrefix("VOIDRAFT")
|
||||
v.AutomaticEnv()
|
||||
|
||||
// 设置默认值
|
||||
setDefaults(v)
|
||||
|
||||
// 构造配置服务实例
|
||||
service := &ConfigService{
|
||||
store: store,
|
||||
viper: v,
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
// 初始化加载配置
|
||||
// 初始化配置
|
||||
if err := service.initConfig(); err != nil {
|
||||
service.logger.Error("Config: Failed to initialize config", "error", err)
|
||||
}
|
||||
|
||||
// 验证并修正配置
|
||||
if err := service.validateAllConfig(); err != nil {
|
||||
service.logger.Error("Config: Failed to validate config", "error", err)
|
||||
}
|
||||
|
||||
// 启动配置文件监听
|
||||
service.startWatching()
|
||||
|
||||
return service
|
||||
}
|
||||
|
||||
// setDefaults 设置默认配置值
|
||||
func setDefaults(v *viper.Viper) {
|
||||
defaultConfig := models.NewDefaultAppConfig()
|
||||
|
||||
// 编辑器配置默认值
|
||||
v.SetDefault("editor.font_size", defaultConfig.Editor.FontSize)
|
||||
v.SetDefault("editor.enable_tab_indent", defaultConfig.Editor.EnableTabIndent)
|
||||
v.SetDefault("editor.tab_size", defaultConfig.Editor.TabSize)
|
||||
v.SetDefault("editor.tab_type", defaultConfig.Editor.TabType)
|
||||
v.SetDefault("editor.language", defaultConfig.Editor.Language)
|
||||
v.SetDefault("editor.always_on_top", defaultConfig.Editor.AlwaysOnTop)
|
||||
|
||||
// 文档配置默认值
|
||||
v.SetDefault("document.auto_save_delay", defaultConfig.Document.AutoSaveDelay)
|
||||
v.SetDefault("document.change_threshold", defaultConfig.Document.ChangeThreshold)
|
||||
v.SetDefault("document.min_save_interval", defaultConfig.Document.MinSaveInterval)
|
||||
|
||||
// 路径配置默认值
|
||||
v.SetDefault("paths.data_path", defaultConfig.Paths.DataPath)
|
||||
|
||||
// 元数据默认值
|
||||
v.SetDefault("metadata.version", defaultConfig.Metadata.Version)
|
||||
v.SetDefault("metadata.last_updated", defaultConfig.Metadata.LastUpdated)
|
||||
}
|
||||
|
||||
// initConfig 初始化配置
|
||||
func (cs *ConfigService) initConfig() error {
|
||||
config, err := cs.loadConfig()
|
||||
cs.mu.Lock()
|
||||
defer cs.mu.Unlock()
|
||||
|
||||
if err != nil {
|
||||
// 如果加载失败,使用默认配置
|
||||
defaultConfig := models.NewDefaultAppConfig()
|
||||
cs.logger.Info("Config: Using default config")
|
||||
|
||||
// 保存默认配置并更新缓存
|
||||
if err := cs.saveConfigWithCache(*defaultConfig); err != nil {
|
||||
return &ConfigError{Operation: "init_save_default", Err: err}
|
||||
// 尝试读取配置文件
|
||||
if err := cs.viper.ReadInConfig(); err != nil {
|
||||
var configFileNotFoundError viper.ConfigFileNotFoundError
|
||||
if errors.As(err, &configFileNotFoundError) {
|
||||
// 配置文件不存在,创建默认配置文件
|
||||
cs.logger.Info("Config: Config file not found, creating default config")
|
||||
return cs.createDefaultConfig()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 合并默认配置
|
||||
if err := cs.mergeWithDefaults(&config); err != nil {
|
||||
return &ConfigError{Operation: "init_merge_defaults", Err: err}
|
||||
// 配置文件存在但读取失败
|
||||
return &ConfigError{Operation: "read_config", Err: err}
|
||||
}
|
||||
|
||||
cs.logger.Info("Config: Successfully loaded config file", "file", cs.viper.ConfigFileUsed())
|
||||
return nil
|
||||
}
|
||||
|
||||
// mergeWithDefaults 将默认配置合并到现有配置中
|
||||
func (cs *ConfigService) mergeWithDefaults(config *models.AppConfig) error {
|
||||
defaultConfig := models.NewDefaultAppConfig()
|
||||
// createDefaultConfig 创建默认配置文件
|
||||
func (cs *ConfigService) createDefaultConfig() error {
|
||||
// 获取配置目录路径
|
||||
currentDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
currentDir = "."
|
||||
}
|
||||
configDir := filepath.Join(currentDir, "config")
|
||||
configPath := filepath.Join(configDir, "config.yaml")
|
||||
|
||||
// 使用mergo库合并配置
|
||||
if err := mergo.Merge(config, defaultConfig, mergo.WithOverrideEmptySlice); err != nil {
|
||||
return err
|
||||
// 确保配置目录存在
|
||||
if err := os.MkdirAll(configDir, 0755); err != nil {
|
||||
return &ConfigError{Operation: "create_config_dir", Err: err}
|
||||
}
|
||||
|
||||
// 更新最后修改时间
|
||||
config.Metadata.LastUpdated = time.Now()
|
||||
// 设置当前时间为最后更新时间
|
||||
cs.viper.Set("metadata.last_updated", time.Now())
|
||||
|
||||
// 保存合并后的配置
|
||||
return cs.saveConfigWithCache(*config)
|
||||
}
|
||||
|
||||
// loadConfig 加载配置
|
||||
func (cs *ConfigService) loadConfig() (models.AppConfig, error) {
|
||||
// 尝试从缓存获取
|
||||
cs.cacheMu.RLock()
|
||||
cachedConfig := cs.cache
|
||||
cs.cacheMu.RUnlock()
|
||||
|
||||
if cachedConfig != nil {
|
||||
return *cachedConfig, nil
|
||||
}
|
||||
|
||||
// 从存储加载
|
||||
config := cs.store.Get()
|
||||
|
||||
// 检查配置是否有效
|
||||
if !isValidConfig(config) {
|
||||
return models.AppConfig{}, errors.New("invalid or empty configuration")
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// isValidConfig 检查配置是否有效
|
||||
func isValidConfig(config models.AppConfig) bool {
|
||||
// 检查关键字段
|
||||
if config.Metadata.Version == "" {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// saveConfigWithCache 保存配置并更新缓存
|
||||
func (cs *ConfigService) saveConfigWithCache(config models.AppConfig) error {
|
||||
// 更新缓存
|
||||
cs.cacheMu.Lock()
|
||||
cs.cache = &config
|
||||
cs.cacheMu.Unlock()
|
||||
|
||||
// 保存到存储
|
||||
if err := cs.store.Set(config); err != nil {
|
||||
return err
|
||||
// 使用 SafeWriteConfigAs 写入配置文件(如果文件不存在则创建)
|
||||
if err := cs.viper.SafeWriteConfigAs(configPath); err != nil {
|
||||
return &ConfigError{Operation: "write_default_config", Err: err}
|
||||
}
|
||||
|
||||
cs.logger.Info("Config: Created default config file", "path", configPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
// startWatching 启动配置文件监听
|
||||
func (cs *ConfigService) startWatching() {
|
||||
// 设置配置变化回调
|
||||
cs.viper.OnConfigChange(func(e fsnotify.Event) {
|
||||
cs.logger.Info("Config: Config file changed", "file", e.Name, "operation", e.Op.String())
|
||||
// 注释掉自动更新时间戳,避免无限循环
|
||||
// err := cs.Set("metadata.last_updated", time.Now())
|
||||
// if err != nil {
|
||||
// cs.logger.Error("Config: Failed to update last_updated field", "error", err)
|
||||
// }
|
||||
})
|
||||
|
||||
// 启动配置文件监听
|
||||
cs.viper.WatchConfig()
|
||||
cs.logger.Info("Config: Started watching config file for changes")
|
||||
}
|
||||
|
||||
// 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.mu.RLock()
|
||||
defer cs.mu.RUnlock()
|
||||
|
||||
var config models.AppConfig
|
||||
if err := cs.viper.Unmarshal(&config); err != nil {
|
||||
return nil, &ConfigError{Operation: "unmarshal_config", Err: err}
|
||||
}
|
||||
cs.cacheMu.RUnlock()
|
||||
|
||||
// 加载配置
|
||||
config, err := cs.loadConfig()
|
||||
if err != nil {
|
||||
// 加载失败,使用默认配置
|
||||
defaultConfig := models.NewDefaultAppConfig()
|
||||
|
||||
// 保存默认配置
|
||||
if saveErr := cs.saveConfigWithCache(*defaultConfig); saveErr != nil {
|
||||
cs.logger.Error("Config: Failed to save default config", "error", saveErr)
|
||||
return nil, &ConfigError{Operation: "get_save_default", Err: saveErr}
|
||||
}
|
||||
|
||||
return defaultConfig, nil
|
||||
}
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
// SaveConfig 保存完整应用配置
|
||||
func (cs *ConfigService) SaveConfig(config *models.AppConfig) error {
|
||||
if config == nil {
|
||||
return errors.New("cannot save nil config")
|
||||
// Set 设置配置项
|
||||
func (cs *ConfigService) Set(key string, value interface{}) error {
|
||||
cs.mu.Lock()
|
||||
defer cs.mu.Unlock()
|
||||
|
||||
// 验证并修正配置值
|
||||
validatedValue, wasFixed := cs.validateAndFixValue(key, value)
|
||||
|
||||
// 设置验证后的值
|
||||
cs.viper.Set(key, validatedValue)
|
||||
|
||||
// 使用 WriteConfig 写入配置文件(会触发文件监听)
|
||||
if err := cs.viper.WriteConfig(); err != nil {
|
||||
return &ConfigError{Operation: "set_config", Err: err}
|
||||
}
|
||||
|
||||
// 更新配置元数据
|
||||
config.Metadata.LastUpdated = time.Now()
|
||||
if wasFixed {
|
||||
cs.logger.Debug("Config: Successfully set config with validation", "key", key, "original", value, "fixed", validatedValue)
|
||||
} else {
|
||||
cs.logger.Debug("Config: Successfully set config", "key", key, "value", value)
|
||||
}
|
||||
|
||||
// 保存配置
|
||||
return cs.saveConfigWithCache(*config)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateEditorConfig 更新编辑器配置
|
||||
func (cs *ConfigService) UpdateEditorConfig(editorConfig models.EditorConfig) error {
|
||||
config, err := cs.GetConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 保存当前的语言设置
|
||||
currentLanguage := config.Editor.Language
|
||||
|
||||
// 更新编辑器配置
|
||||
config.Editor = editorConfig
|
||||
|
||||
// 如果更新后的语言设置为空,则使用之前的语言设置
|
||||
if editorConfig.Language == "" {
|
||||
config.Editor.Language = currentLanguage
|
||||
}
|
||||
|
||||
return cs.SaveConfig(config)
|
||||
}
|
||||
|
||||
// GetEditorConfig 获取编辑器配置
|
||||
func (cs *ConfigService) GetEditorConfig() (models.EditorConfig, error) {
|
||||
config, err := cs.GetConfig()
|
||||
if err != nil {
|
||||
return models.EditorConfig{}, err
|
||||
}
|
||||
return config.Editor, nil
|
||||
}
|
||||
|
||||
// SetLanguage 设置语言
|
||||
func (cs *ConfigService) SetLanguage(language models.LanguageType) error {
|
||||
// 验证语言类型有效
|
||||
if language != models.LangZhCN && language != models.LangEnUS {
|
||||
return errors.New("invalid language type")
|
||||
}
|
||||
|
||||
config, err := cs.GetConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config.Editor.Language = language
|
||||
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
|
||||
}
|
||||
|
||||
// UpdatePaths 更新路径配置
|
||||
func (cs *ConfigService) UpdatePaths(paths models.PathsConfig) error {
|
||||
config, err := cs.GetConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config.Paths = paths
|
||||
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
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// GetMetadata 获取配置元数据
|
||||
func (cs *ConfigService) GetMetadata() (models.ConfigMetadata, error) {
|
||||
config, err := cs.GetConfig()
|
||||
if err != nil {
|
||||
return models.ConfigMetadata{}, err
|
||||
}
|
||||
return config.Metadata, nil
|
||||
// Get 获取配置项
|
||||
func (cs *ConfigService) Get(key string) interface{} {
|
||||
cs.mu.RLock()
|
||||
defer cs.mu.RUnlock()
|
||||
return cs.viper.Get(key)
|
||||
}
|
||||
|
||||
// ResetConfig 重置为默认配置
|
||||
func (cs *ConfigService) ResetConfig() error {
|
||||
defaultConfig := models.NewDefaultAppConfig()
|
||||
return cs.SaveConfig(defaultConfig)
|
||||
cs.mu.Lock()
|
||||
defer cs.mu.Unlock()
|
||||
|
||||
// 重新设置默认值
|
||||
setDefaults(cs.viper)
|
||||
|
||||
// 使用 WriteConfig 写入配置文件(会触发文件监听)
|
||||
if err := cs.viper.WriteConfig(); err != nil {
|
||||
return &ConfigError{Operation: "reset_config", Err: err}
|
||||
}
|
||||
|
||||
cs.logger.Info("Config: Successfully reset to default configuration")
|
||||
return nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user