Private
Public Access
1
0

新增:应用配置管理模块,优化文件系统功能

- 新增 ConfigAPI 和 ConfigService 实现配置管理
- 新增 SettingsPanel 和 UpdateNotification 组件
- 文件系统模块化重构,提升代码质量
- 提取公共函数,优化代码结构
- 版本号更新至 0.2.0
This commit is contained in:
2026-01-28 22:48:10 +08:00
parent 7e79a53dae
commit b849e6cc46
31 changed files with 3024 additions and 917 deletions

View File

@@ -0,0 +1,118 @@
package service
import (
"encoding/json"
"fmt"
"u-desk/internal/storage"
"u-desk/internal/storage/models"
"gorm.io/gorm"
)
// ConfigService 配置服务
type ConfigService struct {
db *gorm.DB
}
// NewConfigService 创建配置服务实例
func NewConfigService() (*ConfigService, error) {
db, err := storage.InitFast()
if err != nil {
return nil, fmt.Errorf("数据库初始化失败: %w", err)
}
return &ConfigService{db: db}, nil
}
// TabDefinition Tab 定义
type TabDefinition struct {
Key string `json:"key"`
Title string `json:"title"`
Enabled bool `json:"enabled"`
}
// TabConfig Tab 配置
type TabConfig struct {
AvailableTabs []TabDefinition `json:"available_tabs"`
VisibleTabs []string `json:"visible_tabs"`
DefaultTab string `json:"default_tab"`
}
// 默认 Tab 配置
var defaultTabConfig = TabConfig{
AvailableTabs: []TabDefinition{
{Key: "db-cli", Title: "数据库", Enabled: true},
{Key: "file-system", Title: "文件管理", Enabled: true},
{Key: "device", Title: "设备调用测试", Enabled: true},
},
VisibleTabs: []string{"db-cli", "file-system", "device"},
DefaultTab: "db-cli",
}
const (
tabConfigKey = "tab_config"
)
// GetTabConfig 获取 Tab 配置
func (s *ConfigService) GetTabConfig() (*TabConfig, error) {
var config models.AppConfig
// 查询配置
err := s.db.Where("`key` = ?", tabConfigKey).First(&config).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
// 不存在配置,返回默认配置
return &defaultTabConfig, nil
}
return nil, fmt.Errorf("查询配置失败: %w", err)
}
// 解析 JSON
var tabConfig TabConfig
if err := json.Unmarshal([]byte(config.Value), &tabConfig); err != nil {
// 解析失败,返回默认配置
return &defaultTabConfig, nil
}
// 验证配置完整性
if len(tabConfig.AvailableTabs) == 0 || len(tabConfig.VisibleTabs) == 0 {
return &defaultTabConfig, nil
}
return &tabConfig, nil
}
// SaveTabConfig 保存 Tab 配置
func (s *ConfigService) SaveTabConfig(config *TabConfig) error {
// 序列化为 JSON
jsonData, err := json.Marshal(config)
if err != nil {
return fmt.Errorf("序列化配置失败: %w", err)
}
// 查询是否存在配置
var existingConfig models.AppConfig
err = s.db.Where("`key` = ?", tabConfigKey).First(&existingConfig).Error
if err == gorm.ErrRecordNotFound {
// 不存在,创建新配置
newConfig := models.AppConfig{
Key: tabConfigKey,
Value: string(jsonData),
Description: "Tab 显示和排序配置",
}
if err := s.db.Create(&newConfig).Error; err != nil {
return fmt.Errorf("创建配置失败: %w", err)
}
} else if err != nil {
return fmt.Errorf("查询配置失败: %w", err)
} else {
// 存在,更新配置
existingConfig.Value = string(jsonData)
if err := s.db.Save(&existingConfig).Error; err != nil {
return fmt.Errorf("更新配置失败: %w", err)
}
}
return nil
}

View File

@@ -10,6 +10,7 @@ import (
"os/exec"
"path/filepath"
"runtime"
"strings"
"time"
)
@@ -27,6 +28,7 @@ type RemoteVersionInfo struct {
Changelog string `json:"changelog"`
ForceUpdate bool `json:"force_update"`
ReleaseDate string `json:"release_date"`
FileSize int64 `json:"file_size"`
}
// UpdateCheckResult 更新检查结果
@@ -38,6 +40,7 @@ type UpdateCheckResult struct {
Changelog string `json:"changelog"`
ForceUpdate bool `json:"force_update"`
ReleaseDate string `json:"release_date"`
FileSize int64 `json:"file_size"`
}
// InstallResult 安装结果
@@ -81,8 +84,13 @@ func (s *UpdateService) CheckUpdate() (*UpdateCheckResult, error) {
return nil, fmt.Errorf("获取远程版本信息失败: %v", err)
}
log.Printf("[更新检查] 远程版本信息: 版本=%s, 下载地址=%s, 强制更新=%v",
remoteInfo.Version, remoteInfo.DownloadURL, remoteInfo.ForceUpdate)
log.Printf("[更新检查] 远程版本信息: 版本=%s, 下载地址=%s, 强制更新=%v, 更新日志长度=%d",
remoteInfo.Version, remoteInfo.DownloadURL, remoteInfo.ForceUpdate, len(remoteInfo.Changelog))
if remoteInfo.Changelog != "" {
log.Printf("[更新检查] 更新日志内容: %s", remoteInfo.Changelog)
} else {
log.Printf("[更新检查] 警告: 远程接口未返回更新日志")
}
// 解析远程版本号
remoteVersion, err := ParseVersion(remoteInfo.Version)
@@ -106,6 +114,7 @@ func (s *UpdateService) CheckUpdate() (*UpdateCheckResult, error) {
Changelog: remoteInfo.Changelog,
ForceUpdate: remoteInfo.ForceUpdate,
ReleaseDate: remoteInfo.ReleaseDate,
FileSize: remoteInfo.FileSize,
}
log.Printf("[更新检查] 检查完成: 有更新=%v", hasUpdate)
@@ -138,13 +147,24 @@ func (s *UpdateService) fetchRemoteVersionInfo() (*RemoteVersionInfo, error) {
log.Printf("[远程版本] 请求远程版本信息: %s", s.checkURL)
// 添加时间戳参数防止缓存
timestamp := time.Now().UnixMilli() // 使用毫秒级时间戳
var requestURL string
if strings.Contains(s.checkURL, "?") {
requestURL = fmt.Sprintf("%s&t=%d", s.checkURL, timestamp)
} else {
requestURL = fmt.Sprintf("%s?t=%d", s.checkURL, timestamp)
}
log.Printf("[远程版本] 实际请求URL: %s", requestURL)
// 创建 HTTP 客户端,设置超时
client := &http.Client{
Timeout: 10 * time.Second,
}
// 发送请求
resp, err := client.Get(s.checkURL)
resp, err := client.Get(requestURL)
if err != nil {
log.Printf("[远程版本] 网络请求失败: %v", err)
return nil, fmt.Errorf("网络请求失败: %v", err)

View File

@@ -44,9 +44,9 @@ func LoadUpdateConfig() (*UpdateConfig, error) {
if _, err := os.Stat(configPath); os.IsNotExist(err) {
return &UpdateConfig{
CurrentVersion: GetCurrentVersion(),
LastCheckTime: time.Time{},
LastCheckTime: time.Time{}, // 启动时会立即检查
AutoCheckEnabled: true,
CheckIntervalMinutes: 1,
CheckIntervalMinutes: 5, // 5分钟检查一次
CheckURL: "https://img.1216.top/u-desk/last-version.json",
}, nil
}

View File

@@ -194,7 +194,8 @@ func DownloadUpdate(downloadURL string, progressCallback DownloadProgress) (*Dow
if elapsed >= 0.3 {
progress := float64(0)
if contentLength > 0 {
progress = normalizeProgress(float64(totalDownloaded) / float64(contentLength) * 100)
rawProgress := float64(totalDownloaded) / float64(contentLength) * 100
progress = normalizeProgress(rawProgress)
}
speed := float64(0)

View File

@@ -13,7 +13,7 @@ import (
// ==================== 常量定义 ====================
// AppVersion 应用版本号(发布时直接修改此处)
const AppVersion = "0.1.0"
const AppVersion = "0.2.0"
// ==================== 类型定义 ====================