♻️ Refactor configuration service

This commit is contained in:
2025-05-28 00:37:18 +08:00
parent 72a222f932
commit 5f102edcf7
18 changed files with 721 additions and 657 deletions

View File

@@ -16,29 +16,24 @@ const (
TabTypeTab TabType = "tab"
)
// SaveOptions 保存选项
type SaveOptions struct {
// 自动保存延迟(毫秒)- 内容变更后多久自动保存
AutoSaveDelay int `json:"autoSaveDelay"`
// 变更字符阈值,超过此阈值立即触发保存
ChangeThreshold int `json:"changeThreshold"`
// 最小保存间隔(毫秒)- 两次保存之间的最小时间间隔避免频繁IO
MinSaveInterval int `json:"minSaveInterval"`
}
// DocumentConfig 定义文档配置
type DocumentConfig struct {
SaveOptions SaveOptions `json:"saveOptions"` // 详细保存选项
// 自动保存延迟(毫秒)- 内容变更后多久自动保存
AutoSaveDelay int `json:"autoSaveDelay" yaml:"auto_save_delay" mapstructure:"auto_save_delay"`
// 变更字符阈值,超过此阈值立即触发保存
ChangeThreshold int `json:"changeThreshold" yaml:"change_threshold" mapstructure:"change_threshold"`
// 最小保存间隔(毫秒)- 两次保存之间的最小时间间隔避免频繁IO
MinSaveInterval int `json:"minSaveInterval" yaml:"min_save_interval" mapstructure:"min_save_interval"`
}
// EditorConfig 定义编辑器配置
type EditorConfig struct {
FontSize int `json:"fontSize"` // 字体大小
EnableTabIndent bool `json:"enableTabIndent"` // 是否启用Tab缩进
TabSize int `json:"tabSize"` // Tab大小
TabType TabType `json:"tabType"` // Tab类型空格或Tab
Language LanguageType `json:"language"` // 界面语言
AlwaysOnTop bool `json:"alwaysOnTop"` // 窗口是否置顶
FontSize int `json:"fontSize" yaml:"font_size" mapstructure:"font_size"` // 字体大小
EnableTabIndent bool `json:"enableTabIndent" yaml:"enable_tab_indent" mapstructure:"enable_tab_indent"` // 是否启用Tab缩进
TabSize int `json:"tabSize" yaml:"tab_size" mapstructure:"tab_size"` // Tab大小
TabType TabType `json:"tabType" yaml:"tab_type" mapstructure:"tab_type"` // Tab类型空格或Tab
Language LanguageType `json:"language" yaml:"language" mapstructure:"language"` // 界面语言
AlwaysOnTop bool `json:"alwaysOnTop" yaml:"always_on_top" mapstructure:"always_on_top"` // 窗口是否置顶
}
// LanguageType 语言类型定义
@@ -53,35 +48,33 @@ const (
// PathsConfig 路径配置集合
type PathsConfig struct {
LogPath string `json:"logPath"` // 日志文件路径
DataPath string `json:"dataPath"` // 数据存储路径
DataPath string `json:"dataPath" yaml:"data_path" mapstructure:"data_path"` // 数据存储路径
}
// AppConfig 应用配置 - 包含业务配置和路径配置
type AppConfig struct {
Editor EditorConfig `json:"editor"` // 编辑器配置
Document DocumentConfig `json:"document"` // 文档配置
Paths PathsConfig `json:"paths"` // 路径配置
Metadata ConfigMetadata `json:"metadata"` // 配置元数据
Editor EditorConfig `json:"editor" yaml:"editor" mapstructure:"editor"` // 编辑器配置
Document DocumentConfig `json:"document" yaml:"document" mapstructure:"document"` // 文档配置
Paths PathsConfig `json:"paths" yaml:"paths" mapstructure:"paths"` // 路径配置
Metadata ConfigMetadata `json:"metadata" yaml:"metadata" mapstructure:"metadata"` // 配置元数据
}
// ConfigMetadata 配置元数据
type ConfigMetadata struct {
Version string `json:"version"` // 配置版本
LastUpdated time.Time `json:"lastUpdated"` // 最后更新时间
Version string `json:"version" yaml:"version" mapstructure:"version"` // 配置版本
LastUpdated time.Time `json:"lastUpdated" yaml:"last_updated" mapstructure:"last_updated"` // 最后更新时间
}
// NewDefaultAppConfig 创建默认应用配置
func NewDefaultAppConfig() *AppConfig {
// 获取用户主目录
homePath, err := os.UserHomeDir()
// 获取当前工作目录
currentDir, err := os.Getwd()
if err != nil {
homePath = "."
currentDir = "."
}
// 默认路径配置
rootDir := filepath.Join(homePath, ".voidraft")
dataDir := filepath.Join(rootDir, "data")
// 默认路径配置 - 使用当前目录
dataDir := filepath.Join(currentDir, "data")
return &AppConfig{
Editor: EditorConfig{
@@ -93,14 +86,11 @@ func NewDefaultAppConfig() *AppConfig {
AlwaysOnTop: false,
},
Document: DocumentConfig{
SaveOptions: SaveOptions{
AutoSaveDelay: 5000, // 5秒后自动保存
ChangeThreshold: 500, // 500个字符变更触发保存
MinSaveInterval: 1000, // 最小间隔1000毫秒
},
AutoSaveDelay: 5000, // 5秒后自动保存
ChangeThreshold: 500, // 500个字符变更触发保存
MinSaveInterval: 1000, // 最小间隔1000毫秒
},
Paths: PathsConfig{
LogPath: filepath.Join(rootDir, "logs"),
DataPath: dataDir,
},
Metadata: ConfigMetadata{

View File

@@ -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
}

View File

@@ -147,9 +147,9 @@ func (ds *DocumentService) scheduleAutoSave() {
// 打印保存设置,便于调试
ds.logger.Debug("Document: Auto save settings",
"autoSaveDelay", config.Document.SaveOptions.AutoSaveDelay,
"changeThreshold", config.Document.SaveOptions.ChangeThreshold,
"minSaveInterval", config.Document.SaveOptions.MinSaveInterval)
"autoSaveDelay", config.Document.AutoSaveDelay,
"changeThreshold", config.Document.ChangeThreshold,
"minSaveInterval", config.Document.MinSaveInterval)
ds.lock.Lock()
defer ds.lock.Unlock()
@@ -160,7 +160,7 @@ func (ds *DocumentService) scheduleAutoSave() {
}
// 创建新的自动保存定时器
autoSaveDelay := config.Document.SaveOptions.AutoSaveDelay
autoSaveDelay := config.Document.AutoSaveDelay
ds.logger.Debug("Document: Scheduling auto save", "delay", autoSaveDelay)
ds.scheduleTimerWithDelay(autoSaveDelay)
}
@@ -197,7 +197,7 @@ func (ds *DocumentService) saveToStore(trigger SaveTrigger) {
// 如果成功获取了配置,使用配置值
if err == nil && config != nil {
minInterval = config.Document.SaveOptions.MinSaveInterval
minInterval = config.Document.MinSaveInterval
}
// 如果是自动保存,检查最小保存间隔
@@ -405,7 +405,7 @@ func (ds *DocumentService) UpdateActiveDocumentContent(content string) error {
// 如果成功获取了配置,使用配置值
if err == nil && config != nil {
threshold = config.Document.SaveOptions.ChangeThreshold
threshold = config.Document.ChangeThreshold
}
ds.lock.Lock()
@@ -530,22 +530,20 @@ func (ds *DocumentService) GetSaveSettings() (*models.DocumentConfig, error) {
// UpdateSaveSettings 更新文档保存设置
func (ds *DocumentService) UpdateSaveSettings(docConfig models.DocumentConfig) error {
// 获取当前配置
config, err := ds.configService.GetConfig()
if err != nil {
return &DocumentError{Operation: "update_save_settings", Err: err}
// 使用配置服务的 Set 方法更新文档配置
if err := ds.configService.Set("document.auto_save_delay", docConfig.AutoSaveDelay); err != nil {
return &DocumentError{Operation: "update_save_settings_auto_save_delay", Err: err}
}
// 更新保存设置
config.Document = docConfig
// 保存配置
err = ds.configService.SaveConfig(config)
if err != nil {
return &DocumentError{Operation: "update_save_settings_save", Err: err}
if err := ds.configService.Set("document.change_threshold", docConfig.ChangeThreshold); err != nil {
return &DocumentError{Operation: "update_save_settings_change_threshold", Err: err}
}
// 安排自动保存(不再需要检查保存模式)
if err := ds.configService.Set("document.min_save_interval", docConfig.MinSaveInterval); err != nil {
return &DocumentError{Operation: "update_save_settings_min_save_interval", Err: err}
}
// 安排自动保存
ds.scheduleAutoSave()
ds.logger.Info("Document: Updated save settings")

View File

@@ -17,11 +17,8 @@ func NewServiceManager() *ServiceManager {
// 初始化日志服务
logger := log.New()
// 初始化配置服务
configService := NewConfigService(ConfigOption{
Logger: logger,
PathProvider: nil,
})
// 初始化配置服务 - 使用固定配置(当前目录下的 config/config.yaml
configService := NewConfigService(logger)
// 初始化文档服务
documentService := NewDocumentService(configService, logger)