重构: 连接切换链收敛与代码清理

- 切换连接统一switchConnection入口,删watcher与抑制机制
- 删除活跃服务器后回落本地并加载
- 侧边栏与指示器点击统一上抛,重复点击可刷新
- Wails事件解析归一,查重谓词抽公共
- 删空壳别名文件与过期文档截图
This commit is contained in:
lxy
2026-09-15 22:26:36 +08:00
parent 6ea9d9ac99
commit 0475d55bff
23 changed files with 395 additions and 351 deletions
+63 -39
View File
@@ -7,10 +7,11 @@ import (
"context"
"fmt"
"log/slog"
"sync"
"time"
"golang.org/x/sync/errgroup"
"u-desk/internal/api"
"u-desk/internal/filewatch"
"u-desk/internal/filesystem"
@@ -123,16 +124,6 @@ func (a *App) ServiceStartup(ctx context.Context, _ application.ServiceOptions)
slog.Warn("配置迁移失败", "error", err)
}
// 2.6. 初始化PDF导出API
slog.Info("初始化PDF导出模块")
pdfAPI, err := api.NewPdfAPI()
if err != nil {
slog.Error("PDF导出API初始化失败", "error", err)
} else {
a.pdfAPI = pdfAPI
slog.Info("PDF导出模块初始化完成")
}
// 3. 初始化版本号(提前触发缓存,避免后续重复计算)
version := service.GetCurrentVersion()
slog.Info("当前版本", "version", version)
@@ -141,13 +132,28 @@ func (a *App) ServiceStartup(ctx context.Context, _ application.ServiceOptions)
visibleTabs := a.getVisibleTabs()
slog.Info("可用的模块", "modules", visibleTabs)
// 4. 根据配置初始化模块(条件初始化)
if err := a.initModulesByConfig(visibleTabs); err != nil {
return fmt.Errorf("模块初始化失败: %w", err)
}
// 非关键路径并行初始化(PdfAPI/Filesystem/Cleanup 不阻塞首屏渲染)
go func() {
// 2.6. 初始化PDF导出API
slog.Info("初始化PDF导出模块")
if pdfAPI, err := api.NewPdfAPI(); err != nil {
slog.Error("PDF导出API初始化失败", "error", err)
} else {
a.mu.Lock()
a.pdfAPI = pdfAPI
a.mu.Unlock()
slog.Info("PDF导出模块初始化完成")
}
// 5. 清理过期的下载缓存
storage.CleanupExpiredCache()
// 根据配置初始化模块(条件初始化)
if err := a.initModulesByConfig(visibleTabs); err != nil {
slog.Error("模块初始化失败", "error", err)
}
// 清理过期的下载缓存
storage.CleanupExpiredCache()
storage.CleanupSiteCacheDirs()
}()
// 6. 异步初始化:UpdateAPI(涉及网络请求,完全异步)
go func() {
@@ -174,8 +180,9 @@ func (a *App) ServiceStartup(ctx context.Context, _ application.ServiceOptions)
// RegisterHotKey 必须在创建窗口的同一线程调用,
// 通过 PostMessage 将注册请求投递到主线程消息循环
go func() {
for i := 0; i < 20; i++ {
time.Sleep(200 * time.Millisecond)
delays := []time.Duration{50 * time.Millisecond, 100 * time.Millisecond, 200 * time.Millisecond}
for i := 0; i < 15; i++ {
time.Sleep(delays[min(i, len(delays)-1)])
if a.mainWindow == nil {
return
}
@@ -203,31 +210,48 @@ func (a *App) ServiceShutdown() error {
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if a.filesystem != nil {
slog.Info("文件系统服务正在关闭")
if err := a.filesystem.Close(shutdownCtx); err != nil {
slog.Error("文件系统服务关闭失败", "error", err)
} else {
g, ctx := errgroup.WithContext(shutdownCtx)
// 并行关闭所有子系统(互不依赖,共享 5s 总超时)
g.Go(func() error {
if a.filesystem != nil {
slog.Info("文件系统服务正在关闭")
if err := a.filesystem.Close(ctx); err != nil {
slog.Error("文件系统服务关闭失败", "error", err)
return err
}
slog.Info("文件系统服务已关闭")
}
}
return nil
})
slog.Info("文件服务器正在关闭")
if err := filesystem.ShutdownLocalFileServer(); err != nil {
slog.Error("文件服务器关闭失败", "error", err)
} else {
g.Go(func() error {
slog.Info("文件服务器正在关闭")
if err := filesystem.ShutdownLocalFileServer(); err != nil {
slog.Error("文件服务器关闭失败", "error", err)
return err
}
slog.Info("文件服务器已关闭")
return nil
})
g.Go(func() error {
if a.sftpService != nil {
sftp.GetManager().Shutdown()
}
storage.CleanupExpiredCache()
storage.CleanupSiteCacheDirs()
return nil
})
g.Go(func() error {
osssvc.GetManager().Shutdown()
return nil
})
if err := g.Wait(); err != nil {
slog.Error("部分子系统关闭失败", "error", err)
}
// 关闭所有 SFTP 连接 + 清理临时文件
if a.sftpService != nil {
sftp.GetManager().Shutdown()
}
storage.CleanupExpiredCache()
// 关闭所有 OSS 连接
osssvc.GetManager().Shutdown()
return nil
}