461 lines
11 KiB
Go
461 lines
11 KiB
Go
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)
|
||
}
|