233 lines
3.2 KiB
Go
233 lines
3.2 KiB
Go
|
package utils
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
|
||
|
"fmt"
|
||
|
|
||
|
"os"
|
||
|
|
||
|
"path/filepath"
|
||
|
|
||
|
"sync"
|
||
|
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
type ConfigVersion struct {
|
||
|
Version int `json:"version"`
|
||
|
UpdatedAt time.Time `json:"updated_at"`
|
||
|
UpdatedBy string `json:"updated_by"`
|
||
|
Comment string `json:"comment"`
|
||
|
}
|
||
|
|
||
|
type ConfigWithVersion struct {
|
||
|
Config *Config `json:"config"`
|
||
|
Version ConfigVersion `json:"version"`
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
configMutex sync.RWMutex
|
||
|
|
||
|
configFile = "config/config.json" // JSON格式更适合动态更新
|
||
|
|
||
|
)
|
||
|
|
||
|
// SaveConfig 保存配置到文件
|
||
|
|
||
|
func SaveConfig(config *Config, updatedBy, comment string) error {
|
||
|
|
||
|
configMutex.Lock()
|
||
|
|
||
|
defer configMutex.Unlock()
|
||
|
|
||
|
// 读取当前版本
|
||
|
|
||
|
currentVersion := 0
|
||
|
|
||
|
if existing, err := LoadPersistedConfig(); err == nil {
|
||
|
|
||
|
currentVersion = existing.Version.Version
|
||
|
|
||
|
}
|
||
|
|
||
|
// 创建新的配置版本
|
||
|
|
||
|
configWithVersion := ConfigWithVersion{
|
||
|
|
||
|
Config: config,
|
||
|
|
||
|
Version: ConfigVersion{
|
||
|
|
||
|
Version: currentVersion + 1,
|
||
|
|
||
|
UpdatedAt: time.Now(),
|
||
|
|
||
|
UpdatedBy: updatedBy,
|
||
|
|
||
|
Comment: comment,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
// 确保配置目录存在
|
||
|
|
||
|
configDir := filepath.Dir(configFile)
|
||
|
|
||
|
if err := os.MkdirAll(configDir, 0755); err != nil {
|
||
|
|
||
|
return err
|
||
|
|
||
|
}
|
||
|
|
||
|
// 备份旧配置
|
||
|
|
||
|
if err := backupConfig(); err != nil {
|
||
|
|
||
|
return err
|
||
|
|
||
|
}
|
||
|
|
||
|
// 将配置转换为JSON
|
||
|
|
||
|
data, err := json.MarshalIndent(configWithVersion, "", " ")
|
||
|
|
||
|
if err != nil {
|
||
|
|
||
|
return err
|
||
|
|
||
|
}
|
||
|
|
||
|
// 写入文件
|
||
|
|
||
|
return os.WriteFile(configFile, data, 0644)
|
||
|
|
||
|
}
|
||
|
|
||
|
// LoadPersistedConfig 加载持久化的配置
|
||
|
|
||
|
func LoadPersistedConfig() (*ConfigWithVersion, error) {
|
||
|
|
||
|
configMutex.RLock()
|
||
|
|
||
|
defer configMutex.RUnlock()
|
||
|
|
||
|
// 检查配置文件是否存在
|
||
|
|
||
|
if _, err := os.Stat(configFile); os.IsNotExist(err) {
|
||
|
|
||
|
// 如果不存在,创建默认配置
|
||
|
|
||
|
config, err := LoadConfig()
|
||
|
|
||
|
if err != nil {
|
||
|
|
||
|
return nil, err
|
||
|
|
||
|
}
|
||
|
|
||
|
return &ConfigWithVersion{
|
||
|
|
||
|
Config: config,
|
||
|
|
||
|
Version: ConfigVersion{
|
||
|
|
||
|
Version: 1,
|
||
|
|
||
|
UpdatedAt: time.Now(),
|
||
|
|
||
|
UpdatedBy: "system",
|
||
|
|
||
|
Comment: "初始配置",
|
||
|
},
|
||
|
}, nil
|
||
|
|
||
|
}
|
||
|
|
||
|
// 读取配置文件
|
||
|
|
||
|
data, err := os.ReadFile(configFile)
|
||
|
|
||
|
if err != nil {
|
||
|
|
||
|
return nil, err
|
||
|
|
||
|
}
|
||
|
|
||
|
// 解析JSON配置
|
||
|
|
||
|
var configWithVersion ConfigWithVersion
|
||
|
|
||
|
if err := json.Unmarshal(data, &configWithVersion); err != nil {
|
||
|
|
||
|
return nil, err
|
||
|
|
||
|
}
|
||
|
|
||
|
return &configWithVersion, nil
|
||
|
|
||
|
}
|
||
|
|
||
|
// MergeConfig 合并配置(环境变量优先)
|
||
|
|
||
|
func MergeConfig(persisted, env *Config) *Config {
|
||
|
|
||
|
if env.Server.Port != "" {
|
||
|
|
||
|
persisted.Server.Port = env.Server.Port
|
||
|
|
||
|
}
|
||
|
|
||
|
if env.Server.Mode != "" {
|
||
|
|
||
|
persisted.Server.Mode = env.Server.Mode
|
||
|
|
||
|
}
|
||
|
|
||
|
// ... 其他配置项的合并 ...
|
||
|
|
||
|
return persisted
|
||
|
|
||
|
}
|
||
|
|
||
|
// backupConfig 备份配置文件
|
||
|
|
||
|
func backupConfig() error {
|
||
|
|
||
|
if _, err := os.Stat(configFile); os.IsNotExist(err) {
|
||
|
|
||
|
return nil
|
||
|
|
||
|
}
|
||
|
|
||
|
// 确保备份目录存在
|
||
|
|
||
|
backupDir := "config/backups"
|
||
|
|
||
|
if err := os.MkdirAll(backupDir, 0755); err != nil {
|
||
|
|
||
|
return err
|
||
|
|
||
|
}
|
||
|
|
||
|
// 读取当前配置
|
||
|
|
||
|
data, err := os.ReadFile(configFile)
|
||
|
|
||
|
if err != nil {
|
||
|
|
||
|
return err
|
||
|
|
||
|
}
|
||
|
|
||
|
// 创建备份文件名
|
||
|
|
||
|
backupFile := filepath.Join(backupDir,
|
||
|
|
||
|
fmt.Sprintf("config_%s.json", time.Now().Format("20060102150405")))
|
||
|
|
||
|
// 写入备份文件
|
||
|
|
||
|
return os.WriteFile(backupFile, data, 0644)
|
||
|
|
||
|
}
|