package main import ( "context" "fmt" "log" "os" "path/filepath" "ssq-desk/internal/api" "ssq-desk/internal/database" "ssq-desk/internal/module" "ssq-desk/internal/service" "ssq-desk/internal/storage/repository" "time" ) // App 应用结构体 type App struct { ctx context.Context moduleManager *module.Manager } // NewApp 创建新的应用实例 func NewApp() *App { manager := module.NewManager() // 注册模块(模块之间相互独立,松散耦合) // SSQ 查询模块 ssqModule, _ := module.NewSsqModule() if ssqModule != nil { manager.Register(ssqModule) } // 授权码模块 authModule, _ := module.NewAuthModule() if authModule != nil { manager.Register(authModule) } // 版本更新模块 updateModule, _ := module.NewUpdateModule() if updateModule != nil { manager.Register(updateModule) } return &App{ moduleManager: manager, } } // initLogFile 初始化日志文件 func initLogFile() { // 获取用户配置目录 appDataDir, err := os.UserConfigDir() if err != nil { // 如果获取失败,使用当前目录 appDataDir = "." } // 创建日志目录 logDir := filepath.Join(appDataDir, "ssq-desk", "logs") if err := os.MkdirAll(logDir, 0755); err != nil { // 如果创建失败,使用当前目录 logDir = "." } // 生成日志文件名(按日期) logFileName := fmt.Sprintf("ssq-desk-%s.log", time.Now().Format("20060102")) logFilePath := filepath.Join(logDir, logFileName) // 打开日志文件(追加模式) logFile, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { // 如果打开失败,继续使用标准输出 return } // 设置日志输出到文件和控制台(同时输出) if logFile != nil { // 创建多写入器,同时写入文件和控制台 multiWriter := &multiWriterType{ file: logFile, console: os.Stdout, } // 设置日志格式:日期时间 + 日志内容 log.SetOutput(multiWriter) log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) log.Printf("[日志] 日志文件已初始化: %s", logFilePath) } else { // 如果无法创建日志文件,使用标准输出 log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) } } // multiWriterType 多写入器,同时写入文件和控制台 type multiWriterType struct { file *os.File console *os.File } func (m *multiWriterType) Write(p []byte) (n int, err error) { // 写入文件 if m.file != nil { m.file.Write(p) } // 写入控制台 if m.console != nil { m.console.Write(p) } return len(p), nil } // startup 应用启动时调用 func (a *App) startup(ctx context.Context) { a.ctx = ctx // 初始化日志文件 initLogFile() // 初始化 SQLite 本地数据库 _, err := database.InitSQLite() if err != nil { log.Printf("[启动] SQLite 初始化失败: %v", err) } else { log.Printf("[启动] SQLite 初始化成功") } // 初始化 MySQL 远程数据库(可选,用于数据同步) _, err = database.InitMySQL() if err != nil { log.Printf("[启动] MySQL 连接失败: %v", err) } else { log.Printf("[启动] MySQL 连接成功") } // 初始化所有模块 if err := a.moduleManager.InitAll(ctx); err != nil { log.Printf("[启动] 模块初始化失败: %v", err) } else { log.Printf("[启动] 模块初始化成功") } // 启动所有模块 if err := a.moduleManager.StartAll(ctx); err != nil { log.Printf("[启动] 模块启动失败: %v", err) } else { log.Printf("[启动] 模块启动成功") } } // getSsqModule 获取 SSQ 模块 func (a *App) getSsqModule() *module.SsqModule { if m, ok := a.moduleManager.Get("ssq"); ok { if ssqModule, ok := m.(*module.SsqModule); ok { return ssqModule } } return nil } // getAuthModule 获取 Auth 模块 func (a *App) getAuthModule() *module.AuthModule { if m, ok := a.moduleManager.Get("auth"); ok { if authModule, ok := m.(*module.AuthModule); ok { return authModule } } return nil } // Greet 测试方法 func (a *App) Greet(name string) string { return "Hello " + name + ", It's show time!" } // QueryHistory 查询历史数据 func (a *App) QueryHistory(req api.QueryRequest) (map[string]interface{}, error) { ssqModule := a.getSsqModule() if ssqModule == nil { _, err := api.NewSsqAPI() return nil, err } ssqAPI := ssqModule.SsqAPI() if ssqAPI == nil { _, err := api.NewSsqAPI() return nil, err } result, err := ssqAPI.QueryHistory(req) if err != nil { return nil, err } // 转换为 map 返回(Wails 需要可序列化的类型) return map[string]interface{}{ "total": result.Total, "summary": result.Summary, "details": result.Details, }, nil } // ActivateLicense 激活授权码 func (a *App) ActivateLicense(licenseCode string) (map[string]interface{}, error) { authModule := a.getAuthModule() if authModule == nil { _, err := api.NewAuthAPI() return nil, err } authAPI := authModule.AuthAPI() if authAPI == nil { _, err := api.NewAuthAPI() return nil, err } return authAPI.ActivateLicense(licenseCode) } // GetAuthStatus 获取授权状态 func (a *App) GetAuthStatus() (map[string]interface{}, error) { authModule := a.getAuthModule() if authModule == nil { _, err := api.NewAuthAPI() return nil, err } authAPI := authModule.AuthAPI() if authAPI == nil { _, err := api.NewAuthAPI() return nil, err } return authAPI.GetAuthStatus() } // GetDeviceID 获取设备ID func (a *App) GetDeviceID() (string, error) { return service.GetDeviceID() } // SyncData 同步数据 func (a *App) SyncData() (map[string]interface{}, error) { syncAPI, err := api.NewSyncAPI() if err != nil { return nil, err } return syncAPI.Sync() } // GetSyncStatus 获取同步状态 func (a *App) GetSyncStatus() (map[string]interface{}, error) { syncAPI, err := api.NewSyncAPI() if err != nil { return nil, err } return syncAPI.GetSyncStatus() } // GetDataStats 获取数据统计 func (a *App) GetDataStats() (map[string]interface{}, error) { ssqModule := a.getSsqModule() if ssqModule == nil { return nil, fmt.Errorf("SSQ 模块未初始化") } repo, err := repository.NewSQLiteSsqRepository() if err != nil { return nil, err } count, err := repo.Count() if err != nil { return nil, err } latestIssue, err := repo.GetLatestIssue() if err != nil { return nil, err } return map[string]interface{}{ "total_count": count, "latest_issue": latestIssue, }, nil } // BackupData 备份数据 func (a *App) BackupData() (map[string]interface{}, error) { backupAPI := api.NewBackupAPI() return backupAPI.Backup() } // RestoreData 恢复数据 func (a *App) RestoreData(backupPath string) (map[string]interface{}, error) { backupAPI := api.NewBackupAPI() return backupAPI.Restore(backupPath) } // ListBackups 列出所有备份 func (a *App) ListBackups() (map[string]interface{}, error) { backupAPI := api.NewBackupAPI() return backupAPI.ListBackups() } // DownloadPackage 下载数据包 func (a *App) DownloadPackage(downloadURL string) (map[string]interface{}, error) { packageAPI, err := api.NewPackageAPI() if err != nil { return nil, err } return packageAPI.DownloadPackage(downloadURL) } // ImportPackage 导入数据包 func (a *App) ImportPackage(packagePath string) (map[string]interface{}, error) { packageAPI, err := api.NewPackageAPI() if err != nil { return nil, err } return packageAPI.ImportPackage(packagePath) } // CheckPackageUpdate 检查数据包更新 func (a *App) CheckPackageUpdate(remoteURL string) (map[string]interface{}, error) { packageAPI, err := api.NewPackageAPI() if err != nil { return nil, err } return packageAPI.CheckPackageUpdate(remoteURL) } // ListLocalPackages 列出本地数据包 func (a *App) ListLocalPackages() (map[string]interface{}, error) { packageAPI, err := api.NewPackageAPI() if err != nil { return nil, err } return packageAPI.ListLocalPackages() } // getUpdateModule 获取更新模块 func (a *App) getUpdateModule() *module.UpdateModule { if m, ok := a.moduleManager.Get("update"); ok { if updateModule, ok := m.(*module.UpdateModule); ok { return updateModule } } return nil } // CheckUpdate 检查更新 func (a *App) CheckUpdate() (map[string]interface{}, error) { updateModule := a.getUpdateModule() if updateModule == nil { return nil, fmt.Errorf("更新模块未初始化") } updateAPI := updateModule.UpdateAPI() if updateAPI == nil { return nil, fmt.Errorf("更新 API 未初始化") } return updateAPI.CheckUpdate() } // GetCurrentVersion 获取当前版本号 func (a *App) GetCurrentVersion() (map[string]interface{}, error) { updateModule := a.getUpdateModule() if updateModule == nil { return nil, fmt.Errorf("更新模块未初始化") } updateAPI := updateModule.UpdateAPI() if updateAPI == nil { return nil, fmt.Errorf("更新 API 未初始化") } return updateAPI.GetCurrentVersion() } // GetUpdateConfig 获取更新配置 func (a *App) GetUpdateConfig() (map[string]interface{}, error) { updateModule := a.getUpdateModule() if updateModule == nil { return nil, fmt.Errorf("更新模块未初始化") } updateAPI := updateModule.UpdateAPI() if updateAPI == nil { return nil, fmt.Errorf("更新 API 未初始化") } return updateAPI.GetUpdateConfig() } // SetUpdateConfig 设置更新配置 func (a *App) SetUpdateConfig(autoCheckEnabled bool, checkIntervalMinutes int, checkURL string) (map[string]interface{}, error) { updateModule := a.getUpdateModule() if updateModule == nil { return nil, fmt.Errorf("更新模块未初始化") } updateAPI := updateModule.UpdateAPI() if updateAPI == nil { return nil, fmt.Errorf("更新 API 未初始化") } return updateAPI.SetUpdateConfig(autoCheckEnabled, checkIntervalMinutes, checkURL) } // DownloadUpdate 下载更新包 func (a *App) DownloadUpdate(downloadURL string) (map[string]interface{}, error) { updateModule := a.getUpdateModule() if updateModule == nil { return nil, fmt.Errorf("更新模块未初始化") } updateAPI := updateModule.UpdateAPI() if updateAPI == nil { return nil, fmt.Errorf("更新 API 未初始化") } // 确保 context 已设置(用于事件推送) if a.ctx != nil { updateAPI.SetContext(a.ctx) } return updateAPI.DownloadUpdate(downloadURL) } // InstallUpdate 安装更新包 func (a *App) InstallUpdate(installerPath string, autoRestart bool) (map[string]interface{}, error) { updateModule := a.getUpdateModule() if updateModule == nil { return nil, fmt.Errorf("更新模块未初始化") } updateAPI := updateModule.UpdateAPI() if updateAPI == nil { return nil, fmt.Errorf("更新 API 未初始化") } return updateAPI.InstallUpdate(installerPath, autoRestart) } // VerifyUpdateFile 验证更新文件哈希值 func (a *App) VerifyUpdateFile(filePath string, expectedHash string, hashType string) (map[string]interface{}, error) { updateModule := a.getUpdateModule() if updateModule == nil { return nil, fmt.Errorf("更新模块未初始化") } updateAPI := updateModule.UpdateAPI() if updateAPI == nil { return nil, fmt.Errorf("更新 API 未初始化") } return updateAPI.VerifyUpdateFile(filePath, expectedHash, hashType) }