Files
ssq-desk/app.go
2026-01-14 14:17:38 +08:00

461 lines
11 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)
}