重构: App拆分10域文件+并发安全+结构化日志+依赖升级
This commit is contained in:
+215
@@ -0,0 +1,215 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"u-desk/internal/api"
|
||||
"u-desk/internal/common"
|
||||
"u-desk/internal/service"
|
||||
"u-desk/internal/storage"
|
||||
"u-desk/internal/storage/models"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ========== 应用配置接口 ==========
|
||||
|
||||
// GetAppConfig 获取应用配置
|
||||
func (a *App) GetAppConfig() (map[string]interface{}, error) {
|
||||
if a.configAPI == nil {
|
||||
return nil, fmt.Errorf("配置服务正在初始化中")
|
||||
}
|
||||
return a.configAPI.GetAppConfig()
|
||||
}
|
||||
|
||||
// SaveAppConfig 保存应用配置
|
||||
func (a *App) SaveAppConfig(req SaveAppConfigRequest) (map[string]interface{}, error) {
|
||||
if a.configAPI == nil {
|
||||
return nil, fmt.Errorf("配置服务正在初始化中")
|
||||
}
|
||||
|
||||
oldConfig, _ := a.configAPI.GetAppConfig()
|
||||
var oldVisibleTabs []string
|
||||
if success, ok := oldConfig["success"].(bool); ok && success {
|
||||
if data, ok := oldConfig["data"].(map[string]interface{}); ok {
|
||||
if vtInterface, ok := data["visibleTabs"].([]interface{}); ok {
|
||||
oldVisibleTabs = common.InterfaceSliceToStringSlice(vtInterface)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apiReq := api.SaveAppConfigRequest{
|
||||
Tabs: req.Tabs,
|
||||
VisibleTabs: req.VisibleTabs,
|
||||
DefaultTab: req.DefaultTab,
|
||||
}
|
||||
|
||||
result, err := a.configAPI.SaveAppConfig(apiReq)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
if success, ok := result["success"].(bool); ok && success {
|
||||
a.handleNewlyEnabledModules(oldVisibleTabs, req.VisibleTabs)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (a *App) LoadConnectionProfiles() ([]map[string]interface{}, error) {
|
||||
list, err := a.ensureProfileSvc().ListProfiles()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var result []map[string]interface{}
|
||||
data, _ := json.Marshal(list)
|
||||
if err := json.Unmarshal(data, &result); err != nil {
|
||||
return nil, fmt.Errorf("解析连接配置失败: %w", err)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (a *App) SaveConnectionProfile(req SaveProfileRequest) (map[string]interface{}, error) {
|
||||
p := &models.ConnectionProfile{
|
||||
Name: req.Name, Host: req.Host, Port: req.Port,
|
||||
Username: req.Username, Password: req.Password,
|
||||
KeyPath: req.KeyPath, Type: req.Type, Provider: req.Provider, Token: req.Token,
|
||||
AccessKey: req.AccessKey, SecretKey: req.SecretKey,
|
||||
Bucket: req.Bucket, Region: req.Region, Endpoint: req.Endpoint,
|
||||
}
|
||||
if req.LastConnected != nil {
|
||||
t := time.Unix(*req.LastConnected, 0)
|
||||
p.LastConnected = &t
|
||||
}
|
||||
if req.ID != nil {
|
||||
p.ID = *req.ID
|
||||
}
|
||||
if err := a.ensureProfileSvc().SaveProfile(p); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return map[string]interface{}{"id": float64(p.ID), "success": true}, nil
|
||||
}
|
||||
|
||||
func (a *App) DeleteConnectionProfile(id uint) error {
|
||||
return a.ensureProfileSvc().DeleteProfile(id)
|
||||
}
|
||||
|
||||
// BgmGetPlaylist 获取播放列表
|
||||
func (a *App) BgmGetPlaylist() ([]BgmPlaylistItem, error) {
|
||||
db := storage.GetDB()
|
||||
if db == nil {
|
||||
return nil, fmt.Errorf("数据库未初始化")
|
||||
}
|
||||
var rows []models.BgmPlaylist
|
||||
if err := db.Order("sort ASC").Find(&rows).Error; err != nil {
|
||||
return nil, fmt.Errorf("查询播放列表失败: %w", err)
|
||||
}
|
||||
items := make([]BgmPlaylistItem, len(rows))
|
||||
for i, r := range rows {
|
||||
items[i] = BgmPlaylistItem{Name: r.Name, Path: r.Path, ProfileID: r.ProfileID}
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
// BgmSavePlaylist 全量保存播放列表(前端调用时传完整列表)
|
||||
func (a *App) BgmSavePlaylist(items []BgmPlaylistItem) error {
|
||||
db := storage.GetDB()
|
||||
if db == nil {
|
||||
return fmt.Errorf("数据库未初始化")
|
||||
}
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.Exec("DELETE FROM bgm_playlist").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
sort := uint(0)
|
||||
for _, item := range items {
|
||||
if item.Name == "" || item.Path == "" {
|
||||
continue
|
||||
}
|
||||
if err := tx.Create(&models.BgmPlaylist{Name: item.Name, Path: item.Path, ProfileID: item.ProfileID, Sort: sort}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
sort++
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (a *App) ensureProfileSvc() *service.ProfileService {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
if a.profileSvc == nil {
|
||||
a.profileSvc = service.NewProfileService()
|
||||
}
|
||||
return a.profileSvc
|
||||
}
|
||||
|
||||
// getVisibleTabs 获取配置中的可见 Tabs
|
||||
func (a *App) getVisibleTabs() []string {
|
||||
config, err := a.configAPI.GetAppConfig()
|
||||
if err != nil {
|
||||
slog.Warn("读取配置失败,使用默认配置", "error", err)
|
||||
return common.DefaultVisibleTabs
|
||||
}
|
||||
|
||||
success, ok := config["success"].(bool)
|
||||
if !ok || !success {
|
||||
slog.Warn("配置读取失败,使用默认配置")
|
||||
return common.DefaultVisibleTabs
|
||||
}
|
||||
|
||||
data, ok := config["data"].(map[string]interface{})
|
||||
if !ok {
|
||||
return common.DefaultVisibleTabs
|
||||
}
|
||||
|
||||
visibleTabsInterface, ok := data["visibleTabs"].([]interface{})
|
||||
if !ok {
|
||||
return common.DefaultVisibleTabs
|
||||
}
|
||||
|
||||
visibleTabs := common.InterfaceSliceToStringSlice(visibleTabsInterface)
|
||||
|
||||
if len(visibleTabs) == 0 {
|
||||
return common.DefaultVisibleTabs
|
||||
}
|
||||
|
||||
return visibleTabs
|
||||
}
|
||||
|
||||
// handleNewlyEnabledModules 处理新启用的模块
|
||||
func (a *App) handleNewlyEnabledModules(oldTabs, newTabs []string) {
|
||||
newlyEnabled := common.Difference(newTabs, oldTabs)
|
||||
|
||||
if len(newlyEnabled) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
slog.Info("检测到新启用的模块", "modules", newlyEnabled)
|
||||
|
||||
for _, tab := range newlyEnabled {
|
||||
switch tab {
|
||||
case common.TabFileSystem:
|
||||
a.initFilesystemModule()
|
||||
case common.TabDevice:
|
||||
slog.Info("设备测试模块已启用")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// initModulesByConfig 根据配置初始化模块
|
||||
func (a *App) initModulesByConfig(visibleTabs []string) error {
|
||||
if common.Contains(visibleTabs, common.TabFileSystem) {
|
||||
a.initFilesystemModule()
|
||||
if a.filesystem == nil {
|
||||
return fmt.Errorf("文件系统服务初始化失败")
|
||||
}
|
||||
} else {
|
||||
slog.Info("跳过文件系统模块(未启用)")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user