新增:应用配置管理模块,优化文件系统功能
- 新增 ConfigAPI 和 ConfigService 实现配置管理 - 新增 SettingsPanel 和 UpdateNotification 组件 - 文件系统模块化重构,提升代码质量 - 提取公共函数,优化代码结构 - 版本号更新至 0.2.0
This commit is contained in:
527
app.go
527
app.go
@@ -3,28 +3,34 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"u-desk/internal/api"
|
||||
"u-desk/internal/database"
|
||||
"u-desk/internal/filesystem"
|
||||
"u-desk/internal/storage"
|
||||
"u-desk/internal/system"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
stdruntime "runtime"
|
||||
"time"
|
||||
|
||||
"u-desk/internal/api"
|
||||
"u-desk/internal/common"
|
||||
"u-desk/internal/database"
|
||||
"u-desk/internal/filesystem"
|
||||
"u-desk/internal/storage"
|
||||
"u-desk/internal/system"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
)
|
||||
|
||||
// App 应用结构体
|
||||
type App struct {
|
||||
ctx context.Context
|
||||
db *database.DB
|
||||
connectionAPI *api.ConnectionAPI
|
||||
sqlAPI *api.SqlAPI
|
||||
tabAPI *api.TabAPI
|
||||
updateAPI *api.UpdateAPI
|
||||
fileServer *http.Server
|
||||
ctx context.Context
|
||||
db *database.DB
|
||||
connectionAPI *api.ConnectionAPI
|
||||
sqlAPI *api.SqlAPI
|
||||
tabAPI *api.TabAPI
|
||||
updateAPI *api.UpdateAPI
|
||||
configAPI *api.ConfigAPI
|
||||
fileServer *http.Server
|
||||
filesystem *filesystem.FileSystemService
|
||||
}
|
||||
|
||||
// NewApp 创建新的应用实例
|
||||
@@ -41,24 +47,119 @@ func (a *App) Startup(ctx context.Context) {
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("SQLite 初始化失败,应用无法启动: %v", err))
|
||||
}
|
||||
_ = sqliteDB // 全局 DB 已由 InitFast() 设置
|
||||
|
||||
// 2. 快速初始化核心 API(都是毫秒级操作,不影响启动速度)
|
||||
if err := a.initCoreAPIs(); err != nil {
|
||||
panic(fmt.Sprintf("核心 API 初始化失败: %v", err))
|
||||
// 2. 初始化配置服务(必需,用于读取模块启用状态)
|
||||
configService, err := api.NewConfigAPI()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("配置服务初始化失败: %v", err))
|
||||
}
|
||||
a.configAPI = configService
|
||||
|
||||
// 3. 读取配置,获取可见的 Tabs
|
||||
visibleTabs := a.getVisibleTabs()
|
||||
fmt.Printf("[启动] 可用的模块: %v\n", visibleTabs)
|
||||
|
||||
// 4. 根据配置初始化模块(条件初始化)
|
||||
if err := a.initModulesByConfig(visibleTabs); err != nil {
|
||||
panic(fmt.Sprintf("模块初始化失败: %v", err))
|
||||
}
|
||||
|
||||
// 3. 异步初始化:文件服务器(不等待)
|
||||
go a.startFileServer()
|
||||
|
||||
// 4. 异步初始化:UpdateAPI(涉及网络请求,完全异步)
|
||||
// 5. 异步初始化:UpdateAPI(涉及网络请求,完全异步)
|
||||
go func() {
|
||||
if updateAPI, err := api.NewUpdateAPI("https://img.1216.top/u-desk/last-version.json"); err == nil {
|
||||
a.updateAPI = updateAPI
|
||||
a.updateAPI.SetContext(ctx)
|
||||
a.startAutoUpdateCheck()
|
||||
}
|
||||
}()
|
||||
|
||||
_ = sqliteDB // 标记已使用
|
||||
}
|
||||
|
||||
// getVisibleTabs 获取配置中的可见 Tabs
|
||||
func (a *App) getVisibleTabs() []string {
|
||||
config, err := a.configAPI.GetAppConfig()
|
||||
if err != nil {
|
||||
fmt.Printf("[启动] 读取配置失败,使用默认配置: %v\n", err)
|
||||
return common.DefaultVisibleTabs
|
||||
}
|
||||
|
||||
// 快速检查成功标识
|
||||
success, ok := config["success"].(bool)
|
||||
if !ok || !success {
|
||||
fmt.Printf("[启动] 配置读取失败,使用默认配置\n")
|
||||
return common.DefaultVisibleTabs
|
||||
}
|
||||
|
||||
// 提取 data
|
||||
data, ok := config["data"].(map[string]interface{})
|
||||
if !ok {
|
||||
return common.DefaultVisibleTabs
|
||||
}
|
||||
|
||||
// 提取 visibleTabs
|
||||
visibleTabsInterface, ok := data["visibleTabs"].([]interface{})
|
||||
if !ok {
|
||||
return common.DefaultVisibleTabs
|
||||
}
|
||||
|
||||
visibleTabs := common.InterfaceSliceToStringSlice(visibleTabsInterface)
|
||||
|
||||
if len(visibleTabs) == 0 {
|
||||
return common.DefaultVisibleTabs
|
||||
}
|
||||
|
||||
return visibleTabs
|
||||
}
|
||||
|
||||
// initModulesByConfig 根据配置初始化模块
|
||||
func (a *App) initModulesByConfig(visibleTabs []string) error {
|
||||
// 检查是否启用数据库模块
|
||||
if common.Contains(visibleTabs, common.TabDatabase) {
|
||||
fmt.Println("[启动] 初始化数据库模块...")
|
||||
var err error
|
||||
|
||||
// 初始化 ConnectionAPI
|
||||
if a.connectionAPI, err = api.NewConnectionAPI(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 初始化 SqlAPI
|
||||
if a.sqlAPI, err = api.NewSqlAPI(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 初始化 TabAPI
|
||||
if a.tabAPI, err = api.NewTabAPI(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("[启动] 数据库模块初始化完成")
|
||||
} else {
|
||||
fmt.Println("[启动] 跳过数据库模块(未启用)")
|
||||
}
|
||||
|
||||
// 检查是否启用文件系统模块
|
||||
if common.Contains(visibleTabs, common.TabFileSystem) {
|
||||
fmt.Println("[启动] 初始化文件系统模块...")
|
||||
|
||||
// 初始化文件系统服务
|
||||
fsConfig := filesystem.DefaultConfig()
|
||||
var err error
|
||||
a.filesystem, err = filesystem.NewFileSystemService(fsConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("文件系统服务初始化失败: %w", err)
|
||||
}
|
||||
|
||||
// 异步启动文件服务器
|
||||
go a.startFileServer()
|
||||
|
||||
fmt.Println("[启动] 文件系统模块初始化完成")
|
||||
} else {
|
||||
fmt.Println("[启动] 跳过文件系统模块(未启用)")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// startFileServer 启动文件服务器
|
||||
@@ -79,6 +180,14 @@ func (a *App) startFileServer() {
|
||||
|
||||
// Shutdown 应用关闭时调用
|
||||
func (a *App) Shutdown(ctx context.Context) {
|
||||
// 关闭文件系统服务(优雅关闭,释放资源)
|
||||
if a.filesystem != nil {
|
||||
fmt.Println("[文件系统服务] 正在关闭...")
|
||||
if err := a.filesystem.Close(ctx); err != nil {
|
||||
fmt.Printf("[文件系统服务] 关闭失败: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 停止文件服务器
|
||||
if a.fileServer != nil {
|
||||
fmt.Println("[文件服务器] 正在关闭...")
|
||||
@@ -138,7 +247,7 @@ func (a *App) GetDiskInfo() ([]map[string]interface{}, error) {
|
||||
|
||||
// ReadFile 读取文件
|
||||
func (a *App) ReadFile(path string) (string, error) {
|
||||
return filesystem.ReadFile(path)
|
||||
return a.filesystem.ReadFile(path)
|
||||
}
|
||||
|
||||
// WriteFileRequest 写入文件请求结构体
|
||||
@@ -149,32 +258,43 @@ type WriteFileRequest struct {
|
||||
|
||||
// WriteFile 写入文件
|
||||
func (a *App) WriteFile(req WriteFileRequest) error {
|
||||
return filesystem.WriteFile(req.Path, req.Content)
|
||||
return a.filesystem.WriteFile(req.Path, req.Content)
|
||||
}
|
||||
|
||||
// ListDir 列出目录
|
||||
func (a *App) ListDir(path string) ([]map[string]interface{}, error) {
|
||||
return filesystem.ListDir(path)
|
||||
return a.filesystem.ListDir(path)
|
||||
}
|
||||
|
||||
// CreateDir 创建目录
|
||||
func (a *App) CreateDir(path string) error {
|
||||
return filesystem.CreateDir(path)
|
||||
return a.filesystem.CreateDir(path)
|
||||
}
|
||||
|
||||
// CreateFile 创建文件
|
||||
func (a *App) CreateFile(path string) error {
|
||||
return filesystem.CreateFile(path)
|
||||
return a.filesystem.CreateFile(path)
|
||||
}
|
||||
|
||||
// DeletePath 删除文件或目录
|
||||
func (a *App) DeletePath(path string) error {
|
||||
return filesystem.DeletePath(path)
|
||||
return a.filesystem.DeletePath(path)
|
||||
}
|
||||
|
||||
// RenamePathRequest 重命名文件或目录请求结构体
|
||||
type RenamePathRequest struct {
|
||||
OldPath string `json:"oldPath"`
|
||||
NewPath string `json:"newPath"`
|
||||
}
|
||||
|
||||
// RenamePath 重命名文件或目录
|
||||
func (a *App) RenamePath(req RenamePathRequest) error {
|
||||
return a.filesystem.RenamePath(req.OldPath, req.NewPath)
|
||||
}
|
||||
|
||||
// GetFileInfo 获取文件信息
|
||||
func (a *App) GetFileInfo(path string) (map[string]interface{}, error) {
|
||||
return filesystem.GetFileInfo(path)
|
||||
return a.filesystem.GetFileInfo(path)
|
||||
}
|
||||
|
||||
// GetEnvVars 获取环境变量
|
||||
@@ -190,30 +310,62 @@ func (a *App) GetEnvVars() (map[string]string, error) {
|
||||
|
||||
// OpenPath 使用系统默认程序打开文件或目录
|
||||
func (a *App) OpenPath(path string) error {
|
||||
return filesystem.OpenPath(path)
|
||||
return a.filesystem.OpenPath(path)
|
||||
}
|
||||
|
||||
// ========== Zip 文件操作接口 ==========
|
||||
|
||||
// ListZipContents 列出 zip 文件内容
|
||||
func (a *App) ListZipContents(zipPath string) ([]map[string]interface{}, error) {
|
||||
return filesystem.ListZipContents(zipPath)
|
||||
return a.filesystem.ListZipContents(zipPath)
|
||||
}
|
||||
|
||||
// ExtractFileFromZip 从 zip 文件中提取单个文件内容
|
||||
func (a *App) ExtractFileFromZip(zipPath, filePath string) (string, error) {
|
||||
return filesystem.ExtractFileFromZip(zipPath, filePath)
|
||||
return a.filesystem.ExtractFileFromZip(zipPath, filePath)
|
||||
}
|
||||
|
||||
// ExtractFileFromZipToTemp 从 zip 文件中提取单个文件到临时目录
|
||||
// 返回临时文件的完整路径,适用于图片等二进制文件
|
||||
func (a *App) ExtractFileFromZipToTemp(zipPath, filePath string) (string, error) {
|
||||
return filesystem.ExtractFileFromZipToTemp(zipPath, filePath)
|
||||
return a.filesystem.ExtractFileFromZipToTemp(zipPath, filePath)
|
||||
}
|
||||
|
||||
// GetZipFileInfo 获取 zip 文件中特定文件的信息
|
||||
func (a *App) GetZipFileInfo(zipPath, filePath string) (map[string]interface{}, error) {
|
||||
return filesystem.GetZipFileInfo(zipPath, filePath)
|
||||
return a.filesystem.GetZipFileInfo(zipPath, filePath)
|
||||
}
|
||||
|
||||
// ResolveShortcut 解析快捷方式文件,返回目标路径信息
|
||||
func (a *App) ResolveShortcut(lnkPath string) (map[string]interface{}, error) {
|
||||
targetPath, err := a.filesystem.ResolveShortcut(lnkPath)
|
||||
if err != nil {
|
||||
return map[string]interface{}{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
}, err
|
||||
}
|
||||
|
||||
// 获取目标文件信息
|
||||
fileInfo, err := a.filesystem.GetFileInfo(targetPath)
|
||||
if err != nil {
|
||||
// 目标文件不存在或无法访问
|
||||
return map[string]interface{}{
|
||||
"success": true,
|
||||
"targetPath": targetPath,
|
||||
"targetExists": false,
|
||||
"targetAccessible": false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 返回完整的目标信息
|
||||
return map[string]interface{}{
|
||||
"success": true,
|
||||
"targetPath": targetPath,
|
||||
"targetExists": true,
|
||||
"targetAccessible": true,
|
||||
"targetInfo": fileInfo,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetCommonPaths 获取常用系统路径
|
||||
@@ -223,9 +375,6 @@ func (a *App) GetCommonPaths() (map[string]string, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 获取所有可用驱动器(Windows)
|
||||
drives := getSystemDrives()
|
||||
|
||||
paths := map[string]string{
|
||||
"home": homeDir,
|
||||
"desktop": filepath.Join(homeDir, "Desktop"),
|
||||
@@ -233,54 +382,22 @@ func (a *App) GetCommonPaths() (map[string]string, error) {
|
||||
"downloads": filepath.Join(homeDir, "Downloads"),
|
||||
}
|
||||
|
||||
// 动态添加所有盘符
|
||||
for _, drive := range drives {
|
||||
key := fmt.Sprintf("root_%s", drive[:1])
|
||||
paths[key] = drive
|
||||
// Windows: 动态添加所有盘符
|
||||
if stdruntime.GOOS == "windows" {
|
||||
for _, drive := range "ABCDEFGHIJKLMNOPQRSTUVWXYZ" {
|
||||
path := string(drive) + ":\\"
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
key := fmt.Sprintf("root_%c", drive)
|
||||
paths[key] = path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return paths, nil
|
||||
}
|
||||
|
||||
// getSystemDrives 获取系统所有可用驱动器
|
||||
func getSystemDrives() []string {
|
||||
var drives []string
|
||||
|
||||
// Windows: 检查 A-Z 所有盘符
|
||||
for _, drive := range "ABCDEFGHIJKLMNOPQRSTUVWXYZ" {
|
||||
path := string(drive) + ":\\"
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
drives = append(drives, path)
|
||||
}
|
||||
}
|
||||
|
||||
return drives
|
||||
}
|
||||
|
||||
// ========== 数据库连接管理接口 ==========
|
||||
|
||||
// initCoreAPIs 初始化核心 API(快速操作,毫秒级完成)
|
||||
func (a *App) initCoreAPIs() error {
|
||||
var err error
|
||||
|
||||
// 初始化 ConnectionAPI
|
||||
if a.connectionAPI, err = api.NewConnectionAPI(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 初始化 SqlAPI
|
||||
if a.sqlAPI, err = api.NewSqlAPI(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 初始化 TabAPI
|
||||
if a.tabAPI, err = api.NewTabAPI(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SaveDbConnection 保存数据库连接配置
|
||||
func (a *App) SaveDbConnection(req api.SaveConnectionRequest) error {
|
||||
return a.connectionAPI.SaveDbConnection(req)
|
||||
@@ -490,16 +607,74 @@ func (a *App) VerifyUpdateFile(filePath string, expectedHash string, hashType st
|
||||
return a.updateAPI.VerifyUpdateFile(filePath, expectedHash, hashType)
|
||||
}
|
||||
|
||||
// ========== 应用生命周期管理 ==========
|
||||
// startAutoUpdateCheck 启动自动更新检查
|
||||
func (a *App) startAutoUpdateCheck() {
|
||||
if a.updateAPI == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// shutdown 应用关闭时调用,清理资源
|
||||
func (a *App) shutdown(ctx context.Context) {
|
||||
// 关闭审计日志
|
||||
filesystem.CloseAudit()
|
||||
config, err := a.updateAPI.GetUpdateConfig()
|
||||
if err != nil || !config["success"].(bool) {
|
||||
return
|
||||
}
|
||||
|
||||
// 停止文件服务器
|
||||
if a.fileServer != nil {
|
||||
_ = a.fileServer.Shutdown(ctx)
|
||||
configData, ok := config["data"].(map[string]interface{})
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
autoCheckEnabled, ok := configData["auto_check_enabled"].(bool)
|
||||
if !ok || !autoCheckEnabled {
|
||||
return
|
||||
}
|
||||
|
||||
interval, ok := configData["check_interval_minutes"].(int)
|
||||
if !ok || interval <= 0 {
|
||||
interval = 5
|
||||
}
|
||||
|
||||
// 立即检查一次
|
||||
go a.checkUpdate()
|
||||
|
||||
// 启动定时器
|
||||
ticker := time.NewTicker(time.Duration(interval) * time.Minute)
|
||||
go func() {
|
||||
for range ticker.C {
|
||||
a.checkUpdate()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// checkUpdate 执行更新检查
|
||||
func (a *App) checkUpdate() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Printf("[自动检查更新] 发生错误: %v\n", r)
|
||||
}
|
||||
}()
|
||||
|
||||
if a.updateAPI == nil {
|
||||
return
|
||||
}
|
||||
|
||||
result, err := a.updateAPI.CheckUpdate()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
success, ok := result["success"].(bool)
|
||||
if !ok || !success {
|
||||
return
|
||||
}
|
||||
|
||||
data, ok := result["data"].(map[string]interface{})
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
hasUpdate, ok := data["has_update"].(bool)
|
||||
if ok && hasUpdate && a.ctx != nil {
|
||||
runtime.EventsEmit(a.ctx, "update-available", data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,29 +682,7 @@ func (a *App) shutdown(ctx context.Context) {
|
||||
|
||||
// GetAuditLogs 获取审计日志
|
||||
func (a *App) GetAuditLogs(limit int) ([]map[string]interface{}, error) {
|
||||
userDataDir := getUserDataDir()
|
||||
logDir := filepath.Join(userDataDir, "logs")
|
||||
|
||||
entries, err := filesystem.GetRecentLogs(logDir, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 转换为map格式
|
||||
result := make([]map[string]interface{}, len(entries))
|
||||
for i, entry := range entries {
|
||||
result[i] = map[string]interface{}{
|
||||
"timestamp": entry.Timestamp.Format("2006-01-02 15:04:05"),
|
||||
"operation": entry.Operation,
|
||||
"path": entry.Path,
|
||||
"size": entry.Size,
|
||||
"is_directory": entry.IsDirectory,
|
||||
"success": entry.Success,
|
||||
"error": entry.Error,
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
return a.filesystem.GetAuditLogs(limit)
|
||||
}
|
||||
|
||||
// ========== 文件服务器接口 ==========
|
||||
@@ -543,53 +696,149 @@ func (a *App) GetFileServerURL() string {
|
||||
|
||||
// GetRecycleBinEntries 获取回收站条目
|
||||
func (a *App) GetRecycleBinEntries() ([]map[string]interface{}, error) {
|
||||
bin := filesystem.GetRecycleBin()
|
||||
if bin == nil {
|
||||
return []map[string]interface{}{}, nil
|
||||
return a.filesystem.GetRecycleBinEntries()
|
||||
}
|
||||
|
||||
// RestoreFromRecycleBin 从回收站恢复文件
|
||||
func (a *App) RestoreFromRecycleBin(recyclePath string) error {
|
||||
return a.filesystem.RestoreFromRecycleBin(recyclePath)
|
||||
}
|
||||
|
||||
// DeletePermanently 永久删除回收站中的文件
|
||||
func (a *App) DeletePermanently(recyclePath string) error {
|
||||
return a.filesystem.DeletePermanently(recyclePath)
|
||||
}
|
||||
|
||||
// EmptyRecycleBin 清空回收站
|
||||
func (a *App) EmptyRecycleBin() error {
|
||||
return a.filesystem.EmptyRecycleBin()
|
||||
}
|
||||
|
||||
// ========== 应用配置接口 ==========
|
||||
|
||||
// GetAppConfig 获取应用配置
|
||||
func (a *App) GetAppConfig() (map[string]interface{}, error) {
|
||||
if a.configAPI == nil {
|
||||
return nil, fmt.Errorf("配置服务正在初始化中")
|
||||
}
|
||||
return a.configAPI.GetAppConfig()
|
||||
}
|
||||
|
||||
// SaveAppConfigRequest 保存应用配置请求
|
||||
type SaveAppConfigRequest struct {
|
||||
Tabs []api.AppTabDefinition `json:"tabs"`
|
||||
VisibleTabs []string `json:"visibleTabs"`
|
||||
DefaultTab string `json:"defaultTab"`
|
||||
}
|
||||
|
||||
// SaveAppConfig 保存应用配置
|
||||
func (a *App) SaveAppConfig(req SaveAppConfigRequest) (map[string]interface{}, error) {
|
||||
if a.configAPI == nil {
|
||||
return nil, fmt.Errorf("配置服务正在初始化中")
|
||||
}
|
||||
|
||||
entries := bin.ListEntries()
|
||||
result := make([]map[string]interface{}, len(entries))
|
||||
|
||||
for i, entry := range entries {
|
||||
result[i] = map[string]interface{}{
|
||||
"original_path": entry.OriginalPath,
|
||||
"deleted_path": entry.DeletedPath,
|
||||
"deleted_time": entry.DeletedTime.Format("2006-01-02 15:04:05"),
|
||||
"size": entry.Size,
|
||||
"is_directory": entry.IsDirectory,
|
||||
// 保存前检查是否有新启用的模块,需要动态初始化
|
||||
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
|
||||
}
|
||||
|
||||
// RestoreFromRecycleBin 从回收站恢复文件
|
||||
func (a *App) RestoreFromRecycleBin(recyclePath string) error {
|
||||
bin := filesystem.GetRecycleBin()
|
||||
if bin == nil {
|
||||
return fmt.Errorf("回收站未初始化")
|
||||
// handleNewlyEnabledModules 处理新启用的模块
|
||||
func (a *App) handleNewlyEnabledModules(oldTabs, newTabs []string) {
|
||||
newlyEnabled := common.Difference(newTabs, oldTabs)
|
||||
|
||||
if len(newlyEnabled) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
return bin.RestoreFromRecycleBin(recyclePath)
|
||||
fmt.Printf("[模块] 检测到新启用的模块: %v\n", newlyEnabled)
|
||||
|
||||
for _, tab := range newlyEnabled {
|
||||
switch tab {
|
||||
case common.TabDatabase:
|
||||
a.initDatabaseModule()
|
||||
case common.TabFileSystem:
|
||||
a.initFilesystemModule()
|
||||
case common.TabDevice:
|
||||
fmt.Println("[模块] 设备测试模块已启用")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeletePermanently 永久删除回收站中的文件
|
||||
func (a *App) DeletePermanently(recyclePath string) error {
|
||||
bin := filesystem.GetRecycleBin()
|
||||
if bin == nil {
|
||||
return fmt.Errorf("回收站未初始化")
|
||||
// initDatabaseModule 延迟初始化数据库模块
|
||||
func (a *App) initDatabaseModule() {
|
||||
if a.connectionAPI != nil {
|
||||
fmt.Println("[模块] 数据库模块已初始化,跳过")
|
||||
return
|
||||
}
|
||||
|
||||
return bin.DeletePermanently(recyclePath)
|
||||
}
|
||||
fmt.Println("[模块] 延迟初始化数据库模块...")
|
||||
var err error
|
||||
|
||||
// EmptyRecycleBin 清空回收站
|
||||
func (a *App) EmptyRecycleBin() error {
|
||||
bin := filesystem.GetRecycleBin()
|
||||
if bin == nil {
|
||||
return fmt.Errorf("回收站未初始化")
|
||||
// 初始化 ConnectionAPI
|
||||
if a.connectionAPI, err = api.NewConnectionAPI(); err != nil {
|
||||
fmt.Printf("[模块] 数据库模块初始化失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
return bin.Empty()
|
||||
// 初始化 SqlAPI
|
||||
if a.sqlAPI, err = api.NewSqlAPI(); err != nil {
|
||||
fmt.Printf("[模块] SqlAPI 初始化失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 初始化 TabAPI
|
||||
if a.tabAPI, err = api.NewTabAPI(); err != nil {
|
||||
fmt.Printf("[模块] TabAPI 初始化失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("[模块] 数据库模块初始化完成")
|
||||
}
|
||||
|
||||
// initFilesystemModule 延迟初始化文件系统模块
|
||||
func (a *App) initFilesystemModule() {
|
||||
if a.filesystem != nil {
|
||||
fmt.Println("[模块] 文件系统模块已初始化,跳过")
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("[模块] 延迟初始化文件系统模块...")
|
||||
fsConfig := filesystem.DefaultConfig()
|
||||
|
||||
var err error
|
||||
a.filesystem, err = filesystem.NewFileSystemService(fsConfig)
|
||||
if err != nil {
|
||||
fmt.Printf("[模块] 文件系统模块初始化失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 启动文件服务器
|
||||
go a.startFileServer()
|
||||
|
||||
fmt.Println("[模块] 文件系统模块初始化完成")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user