This commit is contained in:
2026-01-14 14:17:38 +08:00
commit f1e2ff6563
126 changed files with 13636 additions and 0 deletions

460
app.go Normal file
View File

@@ -0,0 +1,460 @@
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)
}