diff --git a/api/core/middleware/auth.go b/api/core/middleware/auth.go index 8f73d3a8..d6bde9b1 100644 --- a/api/core/middleware/auth.go +++ b/api/core/middleware/auth.go @@ -103,6 +103,7 @@ func AdminAuthMiddleware(secretKey string, redis *redis.Client) gin.HandlerFunc c.Abort() return } + c.Set(types.AdminUserID, claims["user_id"]) } } diff --git a/api/handler/admin/admin_handler.go b/api/handler/admin/admin_handler.go index caf13f7e..51dcdec9 100644 --- a/api/handler/admin/admin_handler.go +++ b/api/handler/admin/admin_handler.go @@ -54,11 +54,11 @@ func (h *ManagerHandler) RegisterRoutes() { // 公开接口,不需要授权 group.POST("login", h.Login) group.GET("logout", h.Logout) - group.GET("session", h.Session) // 需要管理员授权的接口 group.Use(middleware.AdminAuthMiddleware(h.App.Config.AdminSession.SecretKey, h.App.Redis)) { + group.GET("session", h.Session) group.GET("list", h.List) group.POST("save", h.Save) group.POST("enable", h.Enable) @@ -157,16 +157,15 @@ func (h *ManagerHandler) Logout(c *gin.Context) { // Session 会话检测 func (h *ManagerHandler) Session(c *gin.Context) { - id := h.GetLoginUserId(c) - key := fmt.Sprintf("admin/%d", id) - if _, err := h.redis.Get(context.Background(), key).Result(); err != nil { - resp.NotAuth(c) + id := h.GetAdminId(c) + if id == 0 { + resp.NotAuth(c, "当前用户已退出登录") return } var manager model.AdminUser - res := h.DB.Where("id", id).First(&manager) - if res.Error != nil { - resp.NotAuth(c) + err := h.DB.Where("id", id).First(&manager).Error + if err != nil { + resp.NotAuth(c, "当前用户已退出登录") return } diff --git a/api/handler/admin/api_key_handler.go b/api/handler/admin/api_key_handler.go index 653c9a5e..8c66b355 100644 --- a/api/handler/admin/api_key_handler.go +++ b/api/handler/admin/api_key_handler.go @@ -33,7 +33,7 @@ func NewApiKeyHandler(app *core.AppServer, db *gorm.DB) *ApiKeyHandler { // RegisterRoutes 注册路由 func (h *ApiKeyHandler) RegisterRoutes() { - group := h.App.Engine.Group("/api/admin/apiKey/") + group := h.App.Engine.Group("/api/admin/apikey/") // 需要管理员授权的接口 group.Use(middleware.AdminAuthMiddleware(h.App.Config.AdminSession.SecretKey, h.App.Redis)) diff --git a/api/handler/admin/chat_app_handler.go b/api/handler/admin/chat_app_handler.go index 941692da..c22cf34b 100644 --- a/api/handler/admin/chat_app_handler.go +++ b/api/handler/admin/chat_app_handler.go @@ -33,7 +33,7 @@ func NewChatAppHandler(app *core.AppServer, db *gorm.DB) *ChatAppHandler { // RegisterRoutes 注册路由 func (h *ChatAppHandler) RegisterRoutes() { - group := h.App.Engine.Group("/api/admin/app/") + group := h.App.Engine.Group("/api/admin/role/") // 需要管理员授权的接口 group.Use(middleware.AdminAuthMiddleware(h.App.Config.AdminSession.SecretKey, h.App.Redis)) diff --git a/api/handler/admin/config_handler.go b/api/handler/admin/config_handler.go index d10587b7..2bbecf08 100644 --- a/api/handler/admin/config_handler.go +++ b/api/handler/admin/config_handler.go @@ -44,12 +44,12 @@ func NewConfigHandler(app *core.AppServer, db *gorm.DB, levelDB *store.LevelDB, // RegisterRoutes 注册路由 func (h *ConfigHandler) RegisterRoutes() { group := h.App.Engine.Group("/api/admin/config/") + group.GET("get", h.Get) // 需要管理员授权的接口 group.Use(middleware.AdminAuthMiddleware(h.App.Config.AdminSession.SecretKey, h.App.Redis)) { group.POST("update", h.Update) - group.GET("get", h.Get) group.POST("active", h.Active) group.POST("test", h.Test) group.GET("license", h.GetLicense) diff --git a/api/handler/base_handler.go b/api/handler/base_handler.go index cb2b15ca..229cd090 100644 --- a/api/handler/base_handler.go +++ b/api/handler/base_handler.go @@ -15,9 +15,10 @@ import ( logger2 "geekai/logger" "geekai/store/model" "geekai/utils" - "gorm.io/gorm" "strings" + "gorm.io/gorm" + "github.com/gin-gonic/gin" ) @@ -69,6 +70,14 @@ func (h *BaseHandler) GetLoginUserId(c *gin.Context) uint { return uint(utils.IntValue(utils.InterfaceToString(userId), 0)) } +func (h *BaseHandler) GetAdminId(c *gin.Context) uint { + userId, ok := c.Get(types.AdminUserID) + if !ok { + return 0 + } + return uint(utils.IntValue(utils.InterfaceToString(userId), 0)) +} + func (h *BaseHandler) IsLogin(c *gin.Context) bool { return h.GetLoginUserId(c) > 0 } diff --git a/api/handler/captcha_handler.go b/api/handler/captcha_handler.go index 545a5a71..e5284e3a 100644 --- a/api/handler/captcha_handler.go +++ b/api/handler/captcha_handler.go @@ -9,7 +9,6 @@ package handler import ( "geekai/core" - "geekai/core/middleware" "geekai/core/types" "geekai/service" "geekai/utils/resp" @@ -33,14 +32,11 @@ func NewCaptchaHandler(app *core.AppServer, s *service.CaptchaService, sysConfig func (h *CaptchaHandler) RegisterRoutes() { group := h.App.Engine.Group("/api/captcha/") - // 需要用户授权的接口 - group.Use(middleware.UserAuthMiddleware(h.App.Config.Session.SecretKey, h.App.Redis)) - { - group.GET("get", h.Get) - group.POST("check", h.Check) - group.GET("slide/get", h.SlideGet) - group.POST("slide/check", h.SlideCheck) - } + // 无需授权的接口 + group.GET("get", h.Get) + group.POST("check", h.Check) + group.GET("slide/get", h.SlideGet) + group.POST("slide/check", h.SlideCheck) } func (h *CaptchaHandler) Get(c *gin.Context) { diff --git a/api/handler/chat_role_handler.go b/api/handler/chat_role_handler.go index 59b1b2b0..743834a4 100644 --- a/api/handler/chat_role_handler.go +++ b/api/handler/chat_role_handler.go @@ -30,7 +30,7 @@ func NewChatRoleHandler(app *core.AppServer, db *gorm.DB) *ChatRoleHandler { // RegisterRoutes 注册路由 func (h *ChatRoleHandler) RegisterRoutes() { - group := h.App.Engine.Group("/api/role/") + group := h.App.Engine.Group("/api/app/") // 需要用户授权的接口 group.Use(middleware.UserAuthMiddleware(h.App.Config.Session.SecretKey, h.App.Redis)) diff --git a/api/handler/config_handler.go b/api/handler/config_handler.go index 1c92a002..d8422b23 100644 --- a/api/handler/config_handler.go +++ b/api/handler/config_handler.go @@ -9,7 +9,6 @@ package handler import ( "geekai/core" - "geekai/core/middleware" "geekai/service" "geekai/store/model" "geekai/utils" @@ -32,12 +31,9 @@ func NewConfigHandler(app *core.AppServer, db *gorm.DB, licenseService *service. func (h *ConfigHandler) RegisterRoutes() { group := h.App.Engine.Group("/api/config/") - // 需要用户授权的接口 - group.Use(middleware.UserAuthMiddleware(h.App.Config.Session.SecretKey, h.App.Redis)) - { - group.GET("get", h.Get) - group.GET("license", h.License) - } + // 无需授权的接口 + group.GET("get", h.Get) + group.GET("license", h.License) } // Get 获取指定的系统配置 diff --git a/api/handler/function_handler.go b/api/handler/function_handler.go index 6e70f1bd..95e19819 100644 --- a/api/handler/function_handler.go +++ b/api/handler/function_handler.go @@ -58,6 +58,7 @@ func NewFunctionHandler( // RegisterRoutes 注册路由 func (h *FunctionHandler) RegisterRoutes() { group := h.App.Engine.Group("/api/function/") + group.GET("list", h.List) // 需要用户授权的接口 group.Use(middleware.UserAuthMiddleware(h.App.Config.Session.SecretKey, h.App.Redis)) @@ -66,7 +67,6 @@ func (h *FunctionHandler) RegisterRoutes() { group.POST("zaobao", h.ZaoBao) group.POST("dalle3", h.Dall3) group.POST("websearch", h.WebSearch) - group.GET("list", h.List) } } diff --git a/api/handler/menu_handler.go b/api/handler/menu_handler.go index eef28784..d2e3629a 100644 --- a/api/handler/menu_handler.go +++ b/api/handler/menu_handler.go @@ -9,7 +9,6 @@ package handler import ( "geekai/core" - "geekai/core/middleware" "geekai/store/model" "geekai/store/vo" "geekai/utils" @@ -30,12 +29,7 @@ func NewMenuHandler(app *core.AppServer, db *gorm.DB) *MenuHandler { // RegisterRoutes 注册路由 func (h *MenuHandler) RegisterRoutes() { group := h.App.Engine.Group("/api/menu/") - - // 需要用户授权的接口 - group.Use(middleware.UserAuthMiddleware(h.App.Config.Session.SecretKey, h.App.Redis)) - { - group.GET("list", h.List) - } + group.GET("list", h.List) } // List 数据列表 diff --git a/api/handler/net_handler.go b/api/handler/net_handler.go index 4dd0192d..512e80cf 100644 --- a/api/handler/net_handler.go +++ b/api/handler/net_handler.go @@ -35,12 +35,12 @@ func NewNetHandler(app *core.AppServer, db *gorm.DB, manager *oss.UploaderManage // RegisterRoutes 注册路由 func (h *NetHandler) RegisterRoutes() { - group := h.App.Engine.Group("/api/upload/") + group := h.App.Engine.Group("/api/upload") // 需要用户授权的接口 group.Use(middleware.UserAuthMiddleware(h.App.Config.Session.SecretKey, h.App.Redis)) { - group.POST("upload", h.Upload) + group.POST("", h.Upload) group.POST("list", h.List) group.GET("remove", h.Remove) } diff --git a/api/handler/payment_handler.go b/api/handler/payment_handler.go index a1026f94..5d0eeeb8 100644 --- a/api/handler/payment_handler.go +++ b/api/handler/payment_handler.go @@ -12,7 +12,7 @@ import ( "errors" "fmt" "geekai/core" - "geekai/core/midware" + "geekai/core/middleware" "geekai/core/types" "geekai/service" "geekai/service/payment" @@ -81,7 +81,7 @@ func (h *PaymentHandler) RegisterRoutes() { rg.POST("notify/wechat", h.WechatPayNotify) // 需要用户登录的接口 - rg.Use(midware.UserAuthMiddleware(h.App.Config.Session.SecretKey, h.App.Redis)) + rg.Use(middleware.UserAuthMiddleware(h.App.Config.Session.SecretKey, h.App.Redis)) { rg.POST("create", h.Pay) } diff --git a/api/handler/sms_handler.go b/api/handler/sms_handler.go index d1ddaef0..1075a276 100644 --- a/api/handler/sms_handler.go +++ b/api/handler/sms_handler.go @@ -9,7 +9,6 @@ package handler import ( "geekai/core" - "geekai/core/middleware" "geekai/core/types" "geekai/service" "geekai/service/sms" @@ -48,12 +47,8 @@ func NewSmsHandler( // RegisterRoutes 注册路由 func (h *SmsHandler) RegisterRoutes() { group := h.App.Engine.Group("/api/sms/") - - // 需要用户授权的接口 - group.Use(middleware.UserAuthMiddleware(h.App.Config.Session.SecretKey, h.App.Redis)) - { - group.POST("code", h.SendCode) - } + // 无需授权的接口 + group.POST("code", h.SendCode) } // SendCode 发送验证码 diff --git a/api/handler/user_handler.go b/api/handler/user_handler.go index 9dcf53ec..0997ccc7 100644 --- a/api/handler/user_handler.go +++ b/api/handler/user_handler.go @@ -68,12 +68,12 @@ func (h *UserHandler) RegisterRoutes() { group.POST("login", h.Login) group.POST("resetPass", h.ResetPass) group.GET("clogin", h.CLogin) + group.GET("logout", h.Logout) group.GET("clogin/callback", h.CLoginCallback) // 需要用户授权的接口 group.Use(middleware.UserAuthMiddleware(h.App.Config.Session.SecretKey, h.App.Redis)) { - group.GET("logout", h.Logout) group.GET("session", h.Session) group.GET("profile", h.Profile) group.POST("profile/update", h.ProfileUpdate) diff --git a/api/main.go b/api/main.go index f042cee1..24ddb04a 100644 --- a/api/main.go +++ b/api/main.go @@ -112,12 +112,6 @@ func main() { return xdbFS }), - // 数据修复 - fx.Provide(service.NewDataFixService), - fx.Invoke(func(s *core.AppServer, dfs *service.DataFixService) { - dfs.FixData() - }), - // 创建 Ip2Region 查询对象 fx.Provide(func() (*xdb.Searcher, error) { file, err := xdbFS.Open("res/ip2region.xdb") @@ -151,11 +145,9 @@ func main() { fx.Provide(handler.NewJimengHandler), fx.Provide(service.NewConfigService), - fx.Provide(service.NewConfigMigrationService), - fx.Invoke(func(migrationService *service.ConfigMigrationService, config *types.AppConfig, redisClient *redis.Client) { - if err := migrationService.MigrateFromConfig(config); err != nil { - logger.Errorf("配置迁移失败: %v", err) - } + fx.Provide(service.NewMigrationService), + fx.Invoke(func(migrationService *service.MigrationService) { + migrationService.StartMigrate() }), // 管理后台控制器 diff --git a/api/service/data_fix_service.go b/api/service/data_fix_service.go deleted file mode 100644 index 860da884..00000000 --- a/api/service/data_fix_service.go +++ /dev/null @@ -1,66 +0,0 @@ -package service - -import ( - "geekai/store/model" - - "github.com/go-redis/redis/v8" - "gorm.io/gorm" -) - -type DataFixService struct { - db *gorm.DB - redis *redis.Client -} - -func NewDataFixService(db *gorm.DB, redis *redis.Client) *DataFixService { - return &DataFixService{db: db, redis: redis} -} - -func (s *DataFixService) FixData() { - s.FixColumn() -} - -// 字段修正 -func (s *DataFixService) FixColumn() { - // 订单字段整理 - if s.db.Migrator().HasColumn(&model.Order{}, "pay_type") { - s.db.Migrator().RenameColumn(&model.Order{}, "pay_type", "channel") - } - if !s.db.Migrator().HasColumn(&model.Order{}, "check") { - s.db.Migrator().AddColumn(&model.Order{}, "checked") - } - - // 重命名 config 表字段 - if s.db.Migrator().HasColumn(&model.Config{}, "config_json") { - s.db.Migrator().RenameColumn(&model.Config{}, "config_json", "value") - } - if s.db.Migrator().HasColumn(&model.Config{}, "marker") { - s.db.Migrator().RenameColumn(&model.Config{}, "marker", "name") - } - if s.db.Migrator().HasIndex(&model.Config{}, "idx_chatgpt_configs_key") { - s.db.Migrator().DropIndex(&model.Config{}, "idx_chatgpt_configs_key") - } - if s.db.Migrator().HasIndex(&model.Config{}, "marker") { - s.db.Migrator().DropIndex(&model.Config{}, "marker") - } - - // 手动删除字段 - if s.db.Migrator().HasColumn(&model.Order{}, "deleted_at") { - s.db.Migrator().DropColumn(&model.Order{}, "deleted_at") - } - if s.db.Migrator().HasColumn(&model.ChatItem{}, "deleted_at") { - s.db.Migrator().DropColumn(&model.ChatItem{}, "deleted_at") - } - if s.db.Migrator().HasColumn(&model.ChatMessage{}, "deleted_at") { - s.db.Migrator().DropColumn(&model.ChatMessage{}, "deleted_at") - } - if s.db.Migrator().HasColumn(&model.User{}, "chat_config") { - s.db.Migrator().DropColumn(&model.User{}, "chat_config") - } - if s.db.Migrator().HasColumn(&model.ChatModel{}, "category") { - s.db.Migrator().DropColumn(&model.ChatModel{}, "category") - } - if s.db.Migrator().HasColumn(&model.ChatModel{}, "description") { - s.db.Migrator().DropColumn(&model.ChatModel{}, "description") - } -} diff --git a/api/service/license_service.go b/api/service/license_service.go index ea104a55..0b6a949a 100644 --- a/api/service/license_service.go +++ b/api/service/license_service.go @@ -10,37 +10,35 @@ package service import ( "errors" "fmt" - "geekai/core" "geekai/core/types" - "geekai/store" + "geekai/store/model" + "geekai/utils" "strings" "time" "github.com/imroc/req/v3" "github.com/shirou/gopsutil/host" + "gorm.io/gorm" ) type LicenseService struct { - levelDB *store.LevelDB license *types.License urlWhiteList []string machineId string + db *gorm.DB } -func NewLicenseService(server *core.AppServer, levelDB *store.LevelDB) *LicenseService { - var license types.License +func NewLicenseService(sysConfig *types.SystemConfig, db *gorm.DB) *LicenseService { var machineId string - err := levelDB.Get(types.LicenseKey, &license) - logger.Infof("License: %+v", server.SysConfig) info, err := host.Info() if err == nil { machineId = info.HostID } - logger.Infof("License: %+v", license) + logger.Infof("License: %+v", sysConfig.License) return &LicenseService{ - levelDB: levelDB, - license: &license, + license: &sysConfig.License, machineId: machineId, + db: db, } } @@ -88,10 +86,13 @@ func (s *LicenseService) ActiveLicense(license string, machineId string) error { ExpiredAt: res.Data.ExpiredAt, IsActive: true, } - err = s.levelDB.Put(types.LicenseKey, s.license) + + // 保存 License 到数据库 + err = s.db.Model(&model.Config{}).Where("name = ?", types.ConfigKeyLicense).UpdateColumn("value", utils.JsonEncode(s.license)).Error if err != nil { - return fmt.Errorf("保存许可证书失败:%v", err) + return fmt.Errorf("保存 License 到数据库失败: %v", err) } + return nil } @@ -173,6 +174,13 @@ func (s *LicenseService) fetchUrlWhiteList() ([]string, error) { // GetLicense 获取许可信息 func (s *LicenseService) GetLicense() *types.License { + if s.license == nil { + var config model.Config + s.db.Model(&model.Config{}).Where("name = ?", types.ConfigKeyLicense).First(&config) + if config.Value != "" { + utils.JsonDecode(config.Value, &s.license) + } + } return s.license } diff --git a/api/service/config_migration.go b/api/service/migration_service.go similarity index 51% rename from api/service/config_migration.go rename to api/service/migration_service.go index 606741b2..cf5bb8b3 100644 --- a/api/service/config_migration.go +++ b/api/service/migration_service.go @@ -11,6 +11,7 @@ import ( "context" "encoding/json" "geekai/core/types" + "geekai/store" "geekai/store/model" "github.com/go-redis/redis/v8" @@ -24,27 +25,103 @@ const ( MigrationCompleted = "completed" ) -// ConfigMigrationService 配置迁移服务 -type ConfigMigrationService struct { +// MigrationService 配置迁移服务 +type MigrationService struct { db *gorm.DB redisClient *redis.Client + appConfig *types.AppConfig + levelDB *store.LevelDB } -func NewConfigMigrationService(db *gorm.DB, redisClient *redis.Client) *ConfigMigrationService { - return &ConfigMigrationService{ +func NewMigrationService(db *gorm.DB, redisClient *redis.Client, appConfig *types.AppConfig, levelDB *store.LevelDB) *MigrationService { + return &MigrationService{ db: db, redisClient: redisClient, + appConfig: appConfig, + levelDB: levelDB, } } -// MigrateFromConfig 从 config.toml 迁移配置到数据库(仅首次启动时执行) -func (s *ConfigMigrationService) MigrateFromConfig(config *types.AppConfig) error { - // 检查是否已经迁移过 - if s.isMigrationCompleted() { - logger.Info("配置迁移已完成,跳过迁移") - return nil +func (s *MigrationService) StartMigrate() { + go func() { + s.MigrateConfig(s.appConfig) + s.TableMigration() + s.MigrateLicense() + }() +} + +// 迁移 License +func (s *MigrationService) MigrateLicense() { + key := "migrate:license" + if s.redisClient.Get(context.Background(), key).Val() == "1" { + logger.Info("License 已迁移,跳过迁移") + return } + logger.Info("开始迁移 License...") + var license types.License + err := s.levelDB.Get(types.LicenseKey, &license) + if err != nil { + logger.Errorf("迁移 License 失败: %v", err) + return + } + logger.Infof("迁移 License: %+v", license) + if err := s.saveConfig(types.ConfigKeyLicense, license); err != nil { + logger.Errorf("迁移 License 失败: %v", err) + return + } + logger.Info("迁移 License 完成") + s.redisClient.Set(context.Background(), key, "1", 0) +} + +// 数据表迁移 +func (s *MigrationService) TableMigration() { + // 订单字段整理 + if s.db.Migrator().HasColumn(&model.Order{}, "pay_type") { + s.db.Migrator().RenameColumn(&model.Order{}, "pay_type", "channel") + } + if !s.db.Migrator().HasColumn(&model.Order{}, "checked") { + s.db.Migrator().AddColumn(&model.Order{}, "checked") + } + + // 重命名 config 表字段 + if s.db.Migrator().HasColumn(&model.Config{}, "config_json") { + s.db.Migrator().RenameColumn(&model.Config{}, "config_json", "value") + } + if s.db.Migrator().HasColumn(&model.Config{}, "marker") { + s.db.Migrator().RenameColumn(&model.Config{}, "marker", "name") + } + if s.db.Migrator().HasIndex(&model.Config{}, "idx_chatgpt_configs_key") { + s.db.Migrator().DropIndex(&model.Config{}, "idx_chatgpt_configs_key") + } + if s.db.Migrator().HasIndex(&model.Config{}, "marker") { + s.db.Migrator().DropIndex(&model.Config{}, "marker") + } + + // 手动删除字段 + if s.db.Migrator().HasColumn(&model.Order{}, "deleted_at") { + s.db.Migrator().DropColumn(&model.Order{}, "deleted_at") + } + if s.db.Migrator().HasColumn(&model.ChatItem{}, "deleted_at") { + s.db.Migrator().DropColumn(&model.ChatItem{}, "deleted_at") + } + if s.db.Migrator().HasColumn(&model.ChatMessage{}, "deleted_at") { + s.db.Migrator().DropColumn(&model.ChatMessage{}, "deleted_at") + } + if s.db.Migrator().HasColumn(&model.User{}, "chat_config") { + s.db.Migrator().DropColumn(&model.User{}, "chat_config") + } + if s.db.Migrator().HasColumn(&model.ChatModel{}, "category") { + s.db.Migrator().DropColumn(&model.ChatModel{}, "category") + } + if s.db.Migrator().HasColumn(&model.ChatModel{}, "description") { + s.db.Migrator().DropColumn(&model.ChatModel{}, "description") + } +} + +// 迁移配置数据 +func (s *MigrationService) MigrateConfig(config *types.AppConfig) error { + logger.Info("开始迁移配置到数据库...") // 迁移支付配置 @@ -65,36 +142,12 @@ func (s *ConfigMigrationService) MigrateFromConfig(config *types.AppConfig) erro return err } - // 标记迁移完成 - if err := s.markMigrationCompleted(); err != nil { - logger.Errorf("标记迁移完成失败: %v", err) - return err - } - logger.Info("配置迁移完成") return nil } -// 检查是否已经迁移完成 -func (s *ConfigMigrationService) isMigrationCompleted() bool { - ctx := context.Background() - status, err := s.redisClient.Get(ctx, MigrationStatusKey).Result() - if err != nil { - // Redis中没有找到标志,说明未迁移过 - return false - } - return status == MigrationCompleted -} - -// 标记迁移完成 -func (s *ConfigMigrationService) markMigrationCompleted() error { - ctx := context.Background() - // 设置迁移完成标志,永不过期 - return s.redisClient.Set(ctx, MigrationStatusKey, MigrationCompleted, 0).Err() -} - // 迁移支付配置 -func (s *ConfigMigrationService) migratePaymentConfig(config *types.AppConfig) error { +func (s *MigrationService) migratePaymentConfig(config *types.AppConfig) error { paymentConfig := types.PaymentConfig{ Alipay: config.AlipayConfig, @@ -109,7 +162,7 @@ func (s *ConfigMigrationService) migratePaymentConfig(config *types.AppConfig) e } // 迁移存储配置 -func (s *ConfigMigrationService) migrateStorageConfig(config *types.AppConfig) error { +func (s *MigrationService) migrateStorageConfig(config *types.AppConfig) error { ossConfig := types.OSSConfig{ Active: config.OSS.Active, @@ -122,7 +175,7 @@ func (s *ConfigMigrationService) migrateStorageConfig(config *types.AppConfig) e } // 迁移通信配置 -func (s *ConfigMigrationService) migrateCommunicationConfig(config *types.AppConfig) error { +func (s *MigrationService) migrateCommunicationConfig(config *types.AppConfig) error { // SMTP配置 smtpConfig := map[string]any{ "use_tls": config.SmtpConfig.UseTls, @@ -156,7 +209,7 @@ func (s *ConfigMigrationService) migrateCommunicationConfig(config *types.AppCon } // 保存配置到数据库 -func (s *ConfigMigrationService) saveConfig(key string, config any) error { +func (s *MigrationService) saveConfig(key string, config any) error { // 检查是否已存在 var existingConfig model.Config if err := s.db.Where("name", key).First(&existingConfig).Error; err == nil { diff --git a/web/src/components/LoginDialog.vue b/web/src/components/LoginDialog.vue index ba41f8b9..ab97cf85 100644 --- a/web/src/components/LoginDialog.vue +++ b/web/src/components/LoginDialog.vue @@ -34,6 +34,7 @@ @@ -210,6 +211,7 @@ diff --git a/web/src/utils/device.js b/web/src/utils/device.js deleted file mode 100644 index 14553b34..00000000 --- a/web/src/utils/device.js +++ /dev/null @@ -1,133 +0,0 @@ -/** - * 设备检测工具函数 - * 用于判断当前设备类型,支持PC端和移动端的智能识别 - */ - -/** - * 检测设备类型 - * @returns {string} 'mobile' | 'desktop' - */ -export const detectDevice = () => { - const userAgent = navigator.userAgent.toLowerCase() - - // 移动设备关键词检测 - const mobileKeywords = [ - 'mobile', - 'android', - 'iphone', - 'ipad', - 'phone', - 'blackberry', - 'opera mini', - 'windows phone', - 'iemobile', - ] - - // 平板设备关键词检测 - const tabletKeywords = ['tablet', 'ipad', 'playbook', 'silk', 'kindle'] - - // 检查是否为移动设备 - const isMobile = mobileKeywords.some((keyword) => userAgent.includes(keyword)) - - // 检查是否为平板设备 - const isTablet = tabletKeywords.some((keyword) => userAgent.includes(keyword)) - - // 检查屏幕尺寸 - const screenWidth = window.innerWidth - const screenHeight = window.innerHeight - - // 移动设备判断逻辑 - if (isMobile || isTablet || screenWidth <= 768) { - return 'mobile' - } - - return 'desktop' -} - -/** - * 检测是否为移动设备 - * @returns {boolean} - */ -export const isMobileDevice = () => { - return detectDevice() === 'mobile' -} - -/** - * 检测是否为桌面设备 - * @returns {boolean} - */ -export const isDesktopDevice = () => { - return detectDevice() === 'desktop' -} - -/** - * 获取设备跳转路径 - * @param {string} deviceType - 设备类型 - * @param {string} defaultPath - 默认路径 - * @returns {string} 跳转路径 - */ -export const getDeviceRedirectPath = (deviceType, defaultPath = '/') => { - if (deviceType === 'mobile') { - return '/mobile' - } - return defaultPath -} - -/** - * 根据当前设备获取跳转路径 - * @param {string} defaultPath - 默认路径 - * @returns {string} 跳转路径 - */ -export const getCurrentDeviceRedirectPath = (defaultPath = '/') => { - const deviceType = detectDevice() - return getDeviceRedirectPath(deviceType, defaultPath) -} - -/** - * 检测屏幕尺寸 - * @returns {object} { width, height, isSmall, isMedium, isLarge } - */ -export const getScreenInfo = () => { - const width = window.innerWidth - const height = window.innerHeight - - return { - width, - height, - isSmall: width <= 768, - isMedium: width > 768 && width <= 1024, - isLarge: width > 1024, - } -} - -/** - * 检测浏览器类型 - * @returns {string} 浏览器类型 - */ -export const detectBrowser = () => { - const userAgent = navigator.userAgent.toLowerCase() - - if (userAgent.includes('chrome')) return 'chrome' - if (userAgent.includes('firefox')) return 'firefox' - if (userAgent.includes('safari') && !userAgent.includes('chrome')) return 'safari' - if (userAgent.includes('edge')) return 'edge' - if (userAgent.includes('opera')) return 'opera' - - return 'unknown' -} - -/** - * 检测操作系统 - * @returns {string} 操作系统类型 - */ -export const detectOS = () => { - const userAgent = navigator.userAgent.toLowerCase() - - if (userAgent.includes('windows')) return 'windows' - if (userAgent.includes('mac')) return 'macos' - if (userAgent.includes('linux')) return 'linux' - if (userAgent.includes('android')) return 'android' - if (userAgent.includes('ios')) return 'ios' - - return 'unknown' -} diff --git a/web/src/views/Login.vue b/web/src/views/Login.vue index 7489d504..a34b3a18 100644 --- a/web/src/views/Login.vue +++ b/web/src/views/Login.vue @@ -30,12 +30,7 @@