From cd0952e17033798a609321dbcc3d8a6b11537141 Mon Sep 17 00:00:00 2001 From: RockYang Date: Thu, 12 Sep 2024 15:42:09 +0800 Subject: [PATCH 1/2] fixed bug for register page code verification --- CHANGELOG.md | 1 + ...at_role_handler.go => chat_app_handler.go} | 16 +- api/handler/admin/chat_app_type_handler.go | 145 ++++++++++++++++++ api/handler/admin/user_handler.go | 9 +- .../{upload_handler.go => net_handler.go} | 0 api/handler/user_handler.go | 14 ++ api/main.go | 13 +- api/store/model/app_type.go | 11 ++ api/store/vo/app_type.go | 12 ++ web/src/components/LoginDialog.vue | 2 +- web/src/components/admin/AdminSidebar.vue | 14 +- web/src/router.js | 6 + web/src/views/Register.vue | 15 +- web/src/views/admin/AppType.vue | 13 ++ web/src/views/admin/Users.vue | 8 + 15 files changed, 259 insertions(+), 20 deletions(-) rename api/handler/admin/{chat_role_handler.go => chat_app_handler.go} (88%) create mode 100644 api/handler/admin/chat_app_type_handler.go rename api/handler/{upload_handler.go => net_handler.go} (100%) create mode 100644 api/store/model/app_type.go create mode 100644 api/store/vo/app_type.go create mode 100644 web/src/views/admin/AppType.vue diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d3fa220..08e9116e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # 更新日志 ## v4.1.4 * 功能优化:用户文件列表组件增加分页功能支持 +* Bug修复:修复用户注册失败Bug,注册操作只弹出一次行为验证码 ## v4.1.3 * 功能优化:重构用户登录模块,给所有的登录组件增加行为验证码功能,支持用户绑定手机,邮箱和微信 diff --git a/api/handler/admin/chat_role_handler.go b/api/handler/admin/chat_app_handler.go similarity index 88% rename from api/handler/admin/chat_role_handler.go rename to api/handler/admin/chat_app_handler.go index 3776ddc9..8b54eec9 100644 --- a/api/handler/admin/chat_role_handler.go +++ b/api/handler/admin/chat_app_handler.go @@ -22,16 +22,16 @@ import ( "gorm.io/gorm" ) -type ChatRoleHandler struct { +type ChatAppHandler struct { handler.BaseHandler } -func NewChatRoleHandler(app *core.AppServer, db *gorm.DB) *ChatRoleHandler { - return &ChatRoleHandler{BaseHandler: handler.BaseHandler{App: app, DB: db}} +func NewChatAppHandler(app *core.AppServer, db *gorm.DB) *ChatAppHandler { + return &ChatAppHandler{BaseHandler: handler.BaseHandler{App: app, DB: db}} } // Save 创建或者更新某个角色 -func (h *ChatRoleHandler) Save(c *gin.Context) { +func (h *ChatAppHandler) Save(c *gin.Context) { var data vo.ChatRole if err := c.ShouldBindJSON(&data); err != nil { resp.ERROR(c, types.InvalidArgs) @@ -64,7 +64,7 @@ func (h *ChatRoleHandler) Save(c *gin.Context) { resp.SUCCESS(c, data) } -func (h *ChatRoleHandler) List(c *gin.Context) { +func (h *ChatAppHandler) List(c *gin.Context) { var items []model.ChatRole var roles = make([]vo.ChatRole, 0) res := h.DB.Order("sort_num ASC").Find(&items) @@ -108,7 +108,7 @@ func (h *ChatRoleHandler) List(c *gin.Context) { } // Sort 更新角色排序 -func (h *ChatRoleHandler) Sort(c *gin.Context) { +func (h *ChatAppHandler) Sort(c *gin.Context) { var data struct { Ids []uint `json:"ids"` Sorts []int `json:"sorts"` @@ -130,7 +130,7 @@ func (h *ChatRoleHandler) Sort(c *gin.Context) { resp.SUCCESS(c) } -func (h *ChatRoleHandler) Set(c *gin.Context) { +func (h *ChatAppHandler) Set(c *gin.Context) { var data struct { Id uint `json:"id"` Filed string `json:"filed"` @@ -150,7 +150,7 @@ func (h *ChatRoleHandler) Set(c *gin.Context) { resp.SUCCESS(c) } -func (h *ChatRoleHandler) Remove(c *gin.Context) { +func (h *ChatAppHandler) Remove(c *gin.Context) { id := h.GetInt(c, "id", 0) if id <= 0 { diff --git a/api/handler/admin/chat_app_type_handler.go b/api/handler/admin/chat_app_type_handler.go new file mode 100644 index 00000000..2e121a13 --- /dev/null +++ b/api/handler/admin/chat_app_type_handler.go @@ -0,0 +1,145 @@ +package admin + +import ( + "geekai/core" + "geekai/core/types" + "geekai/handler" + "geekai/store/model" + "geekai/store/vo" + "geekai/utils" + "geekai/utils/resp" + "github.com/gin-gonic/gin" + "gorm.io/gorm" +) + +type ChatAppTypeHandler struct { + handler.BaseHandler +} + +func NewChatAppTypeHandler(app *core.AppServer, db *gorm.DB) *ChatAppTypeHandler { + return &ChatAppTypeHandler{BaseHandler: handler.BaseHandler{App: app, DB: db}} +} + +// Save 创建或更新App类型 +func (h *ChatAppTypeHandler) Save(c *gin.Context) { + var data struct { + Id uint `json:"id"` + Name string `json:"name"` + Icon string `json:"icon"` + SortNum int `json:"sort_num"` + } + if err := c.ShouldBindJSON(&data); err != nil { + resp.ERROR(c, types.InvalidArgs) + return + } + + if data.Id == 0 { // for add + err := h.DB.Where("name", data.Name).First(&model.AppType{}).Error + if err == nil { + resp.ERROR(c, "App类型已存在") + return + } + err = h.DB.Create(&model.AppType{ + Name: data.Name, + Icon: data.Icon, + SortNum: data.SortNum, + }).Error + if err != nil { + resp.ERROR(c, err.Error()) + return + } + } else { // for update + err := h.DB.Where("id", data.Id).Updates(map[string]interface{}{ + "name": data.Name, + "icon": data.Icon, + }).Error + if err != nil { + resp.ERROR(c, err.Error()) + return + } + } + resp.SUCCESS(c) +} + +// List 获取App类型列表 +func (h *ChatAppTypeHandler) List(c *gin.Context) { + var items []model.AppType + var appTypes = make([]vo.AppType, 0) + err := h.DB.Order("created_at DESC").Find(&items).Error + if err != nil { + resp.ERROR(c, err.Error()) + return + } + + for _, v := range items { + var appType vo.AppType + err = utils.CopyObject(v, &appType) + if err != nil { + continue + } + appType.Id = v.Id + appType.CreatedAt = v.CreatedAt.Unix() + appTypes = append(appTypes, appType) + } + + resp.SUCCESS(c, appTypes) +} + +// Remove 删除App类型 +func (h *ChatAppTypeHandler) Remove(c *gin.Context) { + id := h.GetInt(c, "id", 0) + + if id <= 0 { + resp.ERROR(c, types.InvalidArgs) + return + } + err := h.DB.Where("id", id).Delete(&model.AppType{}).Error + if err != nil { + resp.ERROR(c, err.Error()) + return + } + resp.SUCCESS(c) +} + +// Enable 启用|禁用 +func (h *ChatAppTypeHandler) Enable(c *gin.Context) { + var data struct { + Id uint `json:"id"` + Enabled bool `json:"enabled"` + } + + if err := c.ShouldBindJSON(&data); err != nil { + resp.ERROR(c, types.InvalidArgs) + return + } + + err := h.DB.Model(&model.AppType{}).Where("id", data.Id).UpdateColumn("enabled", data.Enabled).Error + if err != nil { + resp.ERROR(c, err.Error()) + return + } + resp.SUCCESS(c) +} + +// Sort 更新排序 +func (h *ChatAppTypeHandler) Sort(c *gin.Context) { + var data struct { + Ids []uint `json:"ids"` + Sorts []int `json:"sorts"` + } + + if err := c.ShouldBindJSON(&data); err != nil { + resp.ERROR(c, types.InvalidArgs) + return + } + + for index, id := range data.Ids { + err := h.DB.Model(&model.AppType{}).Where("id", id).Update("sort_num", data.Sorts[index]).Error + if err != nil { + resp.ERROR(c, err.Error()) + return + } + } + + resp.SUCCESS(c) +} diff --git a/api/handler/admin/user_handler.go b/api/handler/admin/user_handler.go index 275be140..6cd03e6a 100644 --- a/api/handler/admin/user_handler.go +++ b/api/handler/admin/user_handler.go @@ -73,6 +73,8 @@ func (h *UserHandler) Save(c *gin.Context) { Id uint `json:"id"` Password string `json:"password"` Username string `json:"username"` + Mobile string `json:"mobile"` + Email string `json:"email"` ChatRoles []string `json:"chat_roles"` ChatModels []int `json:"chat_models"` ExpiredTime string `json:"expired_time"` @@ -102,6 +104,8 @@ func (h *UserHandler) Save(c *gin.Context) { } var oldPower = user.Power user.Username = data.Username + user.Email = data.Email + user.Mobile = data.Mobile user.Status = data.Status user.Vip = data.Vip user.Power = data.Power @@ -109,7 +113,8 @@ func (h *UserHandler) Save(c *gin.Context) { user.ChatModels = utils.JsonEncode(data.ChatModels) user.ExpiredTime = utils.Str2stamp(data.ExpiredTime) - res = h.DB.Select("username", "status", "vip", "power", "chat_roles_json", "chat_models_json", "expired_time").Updates(&user) + res = h.DB.Select("username", "mobile", "email", "status", "vip", "power", "chat_roles_json", "chat_models_json", "expired_time").Updates(&user) + if res.Error != nil { logger.Error("error with update database:", res.Error) resp.ERROR(c, res.Error.Error()) @@ -147,6 +152,8 @@ func (h *UserHandler) Save(c *gin.Context) { u := model.User{ Username: data.Username, Password: utils.GenPassword(data.Password, salt), + Mobile: data.Mobile, + Email: data.Email, Avatar: "/images/avatar/user.png", Salt: salt, Power: data.Power, diff --git a/api/handler/upload_handler.go b/api/handler/net_handler.go similarity index 100% rename from api/handler/upload_handler.go rename to api/handler/net_handler.go diff --git a/api/handler/user_handler.go b/api/handler/user_handler.go index 096da7c5..6b4ab0a9 100644 --- a/api/handler/user_handler.go +++ b/api/handler/user_handler.go @@ -74,6 +74,20 @@ func (h *UserHandler) Register(c *gin.Context) { resp.ERROR(c, types.InvalidArgs) return } + + if h.App.SysConfig.EnabledVerify && data.RegWay == "username" { + var check bool + if data.X != 0 { + check = h.captcha.SlideCheck(data) + } else { + check = h.captcha.Check(data) + } + if !check { + resp.ERROR(c, "请先完人机验证") + return + } + } + data.Password = strings.TrimSpace(data.Password) if len(data.Password) < 8 { resp.ERROR(c, "密码长度不能少于8个字符") diff --git a/api/main.go b/api/main.go index 274f67b2..f240f893 100644 --- a/api/main.go +++ b/api/main.go @@ -146,7 +146,7 @@ func main() { fx.Provide(admin.NewAdminHandler), fx.Provide(admin.NewApiKeyHandler), fx.Provide(admin.NewUserHandler), - fx.Provide(admin.NewChatRoleHandler), + fx.Provide(admin.NewChatAppHandler), fx.Provide(admin.NewRedeemHandler), fx.Provide(admin.NewDashboardHandler), fx.Provide(admin.NewChatModelHandler), @@ -338,7 +338,7 @@ func main() { group.GET("loginLog", h.LoginLog) group.POST("resetPass", h.ResetPass) }), - fx.Invoke(func(s *core.AppServer, h *admin.ChatRoleHandler) { + fx.Invoke(func(s *core.AppServer, h *admin.ChatAppHandler) { group := s.Engine.Group("/api/admin/role/") group.GET("list", h.List) group.POST("save", h.Save) @@ -502,6 +502,15 @@ func main() { group.GET("remove", h.Remove) group.GET("publish", h.Publish) }), + fx.Provide(admin.NewChatAppTypeHandler), + fx.Invoke(func(s *core.AppServer, h *admin.ChatAppTypeHandler) { + group := s.Engine.Group("/api/admin/app/type") + group.POST("save", h.Save) + group.GET("list", h.List) + group.GET("remove", h.Remove) + group.POST("enable", h.Enable) + group.POST("sort", h.Sort) + }), fx.Provide(handler.NewTestHandler), fx.Invoke(func(s *core.AppServer, h *handler.TestHandler) { group := s.Engine.Group("/api/test") diff --git a/api/store/model/app_type.go b/api/store/model/app_type.go new file mode 100644 index 00000000..de10cb16 --- /dev/null +++ b/api/store/model/app_type.go @@ -0,0 +1,11 @@ +package model + +import "time" + +type AppType struct { + Id uint `gorm:"primarykey"` + Name string + Icon string + SortNum int + CreatedAt time.Time +} diff --git a/api/store/vo/app_type.go b/api/store/vo/app_type.go new file mode 100644 index 00000000..714b398a --- /dev/null +++ b/api/store/vo/app_type.go @@ -0,0 +1,12 @@ +package vo + +type AppType struct { + BaseVo + Name string `json:"name"` + Type string `json:"type"` + Value string `json:"value"` // API Key 的值 + ApiURL string `json:"api_url"` + Enabled bool `json:"enabled"` + ProxyURL string `json:"proxy_url"` + LastUsedAt int64 `json:"last_used_at"` // 最后使用时间 +} diff --git a/web/src/components/LoginDialog.vue b/web/src/components/LoginDialog.vue index 9c9de180..6af69740 100644 --- a/web/src/components/LoginDialog.vue +++ b/web/src/components/LoginDialog.vue @@ -384,7 +384,7 @@ const submitRegister = () => { if ((activeName.value === 'mobile' || activeName.value === 'email') && data.value.code === '') { return ElMessage.error('请输入验证码'); } - if (enableVerify.value) { + if (enableVerify.value && activeName.value === 'username') { captchaRef.value.loadCaptcha() action.value = "register" } else { diff --git a/web/src/components/admin/AdminSidebar.vue b/web/src/components/admin/AdminSidebar.vue index 7034fc10..22b7bea8 100644 --- a/web/src/components/admin/AdminSidebar.vue +++ b/web/src/components/admin/AdminSidebar.vue @@ -90,12 +90,22 @@ const items = [ index: '/admin/user', title: '用户管理', }, - { icon: 'menu', - index: '/admin/app', + index: '1', title: '应用管理', + subs: [ + { + index: '/admin/app', + title: '应用列表', + }, + { + index: '/admin/app/type', + title: '应用分类', + }, + ], }, + { icon: 'api-key', index: '/admin/apikey', diff --git a/web/src/router.js b/web/src/router.js index fe33991c..8507382a 100644 --- a/web/src/router.js +++ b/web/src/router.js @@ -173,6 +173,12 @@ const routes = [ meta: {title: '应用管理'}, component: () => import('@/views/admin/Apps.vue'), }, + { + path: '/admin/app/type', + name: 'admin-app-type', + meta: {title: '应用管理'}, + component: () => import('@/views/admin/AppType.vue'), + }, { path: '/admin/apikey', name: 'admin-apikey', diff --git a/web/src/views/Register.vue b/web/src/views/Register.vue index e5c8354e..53840151 100644 --- a/web/src/views/Register.vue +++ b/web/src/views/Register.vue @@ -16,7 +16,7 @@
+ + @@ -73,6 +75,12 @@ + + + + + + From c18d272413924df1b779b9cc66baa856a4858ffc Mon Sep 17 00:00:00 2001 From: RockYang Date: Thu, 12 Sep 2024 17:25:19 +0800 Subject: [PATCH 2/2] fixed bug for reset password --- api/core/app_server.go | 3 +- api/handler/admin/api_key_handler.go | 4 -- api/handler/admin/chat_app_type_handler.go | 13 ++++--- api/handler/chat_app_type_handler.go | 43 ++++++++++++++++++++++ api/handler/chat_role_handler.go | 36 ++++++++++++++++-- api/handler/user_handler.go | 2 +- api/main.go | 3 +- api/service/smtp_sms_service.go | 2 +- api/store/model/app_type.go | 1 + api/store/vo/app_type.go | 14 +++---- database/update-v4.1.4.sql | 12 ++++++ web/src/views/ChatApps.vue | 5 +-- web/src/views/ChatPlus.vue | 2 +- web/src/views/mobile/ChatList.vue | 4 +- web/src/views/mobile/ChatSession.vue | 2 +- web/src/views/mobile/Index.vue | 2 +- 16 files changed, 115 insertions(+), 33 deletions(-) create mode 100644 api/handler/chat_app_type_handler.go create mode 100644 database/update-v4.1.4.sql diff --git a/api/core/app_server.go b/api/core/app_server.go index b7187d21..e911af72 100644 --- a/api/core/app_server.go +++ b/api/core/app_server.go @@ -204,7 +204,8 @@ func needLogin(c *gin.Context) bool { c.Request.URL.Path == "/api/chat/history" || c.Request.URL.Path == "/api/chat/detail" || c.Request.URL.Path == "/api/chat/list" || - c.Request.URL.Path == "/api/role/list" || + c.Request.URL.Path == "/api/app/list" || + c.Request.URL.Path == "/api/app/list/user" || c.Request.URL.Path == "/api/model/list" || c.Request.URL.Path == "/api/mj/imgWall" || c.Request.URL.Path == "/api/mj/client" || diff --git a/api/handler/admin/api_key_handler.go b/api/handler/admin/api_key_handler.go index ef1d93d1..b6454252 100644 --- a/api/handler/admin/api_key_handler.go +++ b/api/handler/admin/api_key_handler.go @@ -74,7 +74,6 @@ func (h *ApiKeyHandler) Save(c *gin.Context) { func (h *ApiKeyHandler) List(c *gin.Context) { status := h.GetBool(c, "status") t := h.GetTrim(c, "type") - platform := h.GetTrim(c, "platform") session := h.DB.Session(&gorm.Session{}) if status { @@ -83,9 +82,6 @@ func (h *ApiKeyHandler) List(c *gin.Context) { if t != "" { session = session.Where("type", t) } - if platform != "" { - session = session.Where("platform", platform) - } var items []model.ApiKey var keys = make([]vo.ApiKey, 0) diff --git a/api/handler/admin/chat_app_type_handler.go b/api/handler/admin/chat_app_type_handler.go index 2e121a13..d462f42c 100644 --- a/api/handler/admin/chat_app_type_handler.go +++ b/api/handler/admin/chat_app_type_handler.go @@ -25,6 +25,7 @@ func (h *ChatAppTypeHandler) Save(c *gin.Context) { var data struct { Id uint `json:"id"` Name string `json:"name"` + Enable bool `json:"enable"` Icon string `json:"icon"` SortNum int `json:"sort_num"` } @@ -36,12 +37,13 @@ func (h *ChatAppTypeHandler) Save(c *gin.Context) { if data.Id == 0 { // for add err := h.DB.Where("name", data.Name).First(&model.AppType{}).Error if err == nil { - resp.ERROR(c, "App类型已存在") + resp.ERROR(c, "当前分类已经存在") return } err = h.DB.Create(&model.AppType{ Name: data.Name, Icon: data.Icon, + Enabled: data.Enable, SortNum: data.SortNum, }).Error if err != nil { @@ -49,9 +51,10 @@ func (h *ChatAppTypeHandler) Save(c *gin.Context) { return } } else { // for update - err := h.DB.Where("id", data.Id).Updates(map[string]interface{}{ - "name": data.Name, - "icon": data.Icon, + err := h.DB.Model(&model.AppType{}).Where("id", data.Id).Updates(map[string]interface{}{ + "name": data.Name, + "icon": data.Icon, + "enabled": data.Enable, }).Error if err != nil { resp.ERROR(c, err.Error()) @@ -65,7 +68,7 @@ func (h *ChatAppTypeHandler) Save(c *gin.Context) { func (h *ChatAppTypeHandler) List(c *gin.Context) { var items []model.AppType var appTypes = make([]vo.AppType, 0) - err := h.DB.Order("created_at DESC").Find(&items).Error + err := h.DB.Order("sort_num ASC").Find(&items).Error if err != nil { resp.ERROR(c, err.Error()) return diff --git a/api/handler/chat_app_type_handler.go b/api/handler/chat_app_type_handler.go new file mode 100644 index 00000000..fc5e277e --- /dev/null +++ b/api/handler/chat_app_type_handler.go @@ -0,0 +1,43 @@ +package handler + +import ( + "geekai/core" + "geekai/store/model" + "geekai/store/vo" + "geekai/utils" + "geekai/utils/resp" + "github.com/gin-gonic/gin" + "gorm.io/gorm" +) + +type ChatAppTypeHandler struct { + BaseHandler +} + +func NewChatAppTypeHandler(app *core.AppServer, db *gorm.DB) *ChatAppTypeHandler { + return &ChatAppTypeHandler{BaseHandler: BaseHandler{App: app, DB: db}} +} + +// List 获取App类型列表 +func (h *ChatAppTypeHandler) List(c *gin.Context) { + var items []model.AppType + var appTypes = make([]vo.AppType, 0) + err := h.DB.Order("sort_num ASC").Find(&items).Error + if err != nil { + resp.ERROR(c, err.Error()) + return + } + + for _, v := range items { + var appType vo.AppType + err = utils.CopyObject(v, &appType) + if err != nil { + continue + } + appType.Id = v.Id + appType.CreatedAt = v.CreatedAt.Unix() + appTypes = append(appTypes, appType) + } + + resp.SUCCESS(c, appTypes) +} diff --git a/api/handler/chat_role_handler.go b/api/handler/chat_role_handler.go index ce18ec8e..8ef899be 100644 --- a/api/handler/chat_role_handler.go +++ b/api/handler/chat_role_handler.go @@ -29,10 +29,37 @@ func NewChatRoleHandler(app *core.AppServer, db *gorm.DB) *ChatRoleHandler { // List 获取用户聊天应用列表 func (h *ChatRoleHandler) List(c *gin.Context) { + tid := h.GetInt(c, "tid", 0) + var roles []model.ChatRole + session := h.DB.Where("enable", true) + if tid > 0 { + session = session.Where("tid", tid) + } + err := session.Order("sort_num ASC").Find(&roles).Error + if err != nil { + resp.ERROR(c, err.Error()) + return + } + + var roleVos = make([]vo.ChatRole, 0) + for _, r := range roles { + var v vo.ChatRole + err := utils.CopyObject(r, &v) + if err == nil { + v.Id = r.Id + roleVos = append(roleVos, v) + } + } + resp.SUCCESS(c, roleVos) +} + +// ListByUser 获取用户添加的角色列表 +func (h *ChatRoleHandler) ListByUser(c *gin.Context) { id := h.GetInt(c, "id", 0) userId := h.GetLoginUserId(c) var roles []model.ChatRole - query := h.DB.Where("enable", true) + session := h.DB.Where("enable", true) + // 如果用户没登录,则获取所有角色 if userId > 0 { var user model.User h.DB.First(&user, userId) @@ -42,12 +69,13 @@ func (h *ChatRoleHandler) List(c *gin.Context) { resp.ERROR(c, "角色解析失败!") return } - query = query.Where("marker IN ?", roleKeys) + session = session.Where("marker IN ?", roleKeys) } + if id > 0 { - query = query.Or("id", id) + session = session.Or("id", id) } - res := h.DB.Where("enable", true).Order("sort_num ASC").Find(&roles) + res := session.Order("sort_num ASC").Find(&roles) if res.Error != nil { resp.ERROR(c, res.Error.Error()) return diff --git a/api/handler/user_handler.go b/api/handler/user_handler.go index 6b4ab0a9..de7a9657 100644 --- a/api/handler/user_handler.go +++ b/api/handler/user_handler.go @@ -601,7 +601,7 @@ func (h *UserHandler) ResetPass(c *gin.Context) { session = session.Where("email", data.Email) key = CodeStorePrefix + data.Email } else if data.Type == "mobile" { - session = session.Where("mobile", data.Email) + session = session.Where("mobile", data.Mobile) key = CodeStorePrefix + data.Mobile } else { resp.ERROR(c, "验证类别错误") diff --git a/api/main.go b/api/main.go index f240f893..dd725536 100644 --- a/api/main.go +++ b/api/main.go @@ -226,8 +226,9 @@ func main() { // 注册路由 fx.Invoke(func(s *core.AppServer, h *handler.ChatRoleHandler) { - group := s.Engine.Group("/api/role/") + group := s.Engine.Group("/api/app/") group.GET("list", h.List) + group.GET("list/user", h.ListByUser) group.POST("update", h.UpdateRole) }), fx.Invoke(func(s *core.AppServer, h *handler.UserHandler) { diff --git a/api/service/smtp_sms_service.go b/api/service/smtp_sms_service.go index 025ffa39..c6abf586 100644 --- a/api/service/smtp_sms_service.go +++ b/api/service/smtp_sms_service.go @@ -29,7 +29,7 @@ func NewSmtpService(appConfig *types.AppConfig) *SmtpService { func (s *SmtpService) SendVerifyCode(to string, code int) error { subject := fmt.Sprintf("%s 注册验证码", s.config.AppName) - body := fmt.Sprintf("您正在注册 %s 账户,注册验证码为 %d,请不要告诉他人。如非本人操作,请忽略此邮件。", s.config.AppName, code) + body := fmt.Sprintf("【%s】:您的验证码为 %d,请不要告诉他人。如非本人操作,请忽略此邮件。", s.config.AppName, code) auth := smtp.PlainAuth("", s.config.From, s.config.Password, s.config.Host) if s.config.UseTls { diff --git a/api/store/model/app_type.go b/api/store/model/app_type.go index de10cb16..ee1aceed 100644 --- a/api/store/model/app_type.go +++ b/api/store/model/app_type.go @@ -6,6 +6,7 @@ type AppType struct { Id uint `gorm:"primarykey"` Name string Icon string + Enabled bool SortNum int CreatedAt time.Time } diff --git a/api/store/vo/app_type.go b/api/store/vo/app_type.go index 714b398a..26dfe345 100644 --- a/api/store/vo/app_type.go +++ b/api/store/vo/app_type.go @@ -1,12 +1,10 @@ package vo type AppType struct { - BaseVo - Name string `json:"name"` - Type string `json:"type"` - Value string `json:"value"` // API Key 的值 - ApiURL string `json:"api_url"` - Enabled bool `json:"enabled"` - ProxyURL string `json:"proxy_url"` - LastUsedAt int64 `json:"last_used_at"` // 最后使用时间 + Id uint `json:"id"` + Name string `json:"name"` + Icon string `json:"icon"` + SortNum int `json:"sort_num"` + Enabled bool `json:"enabled"` + CreatedAt int64 `json:"created_at"` } diff --git a/database/update-v4.1.4.sql b/database/update-v4.1.4.sql new file mode 100644 index 00000000..86d47b63 --- /dev/null +++ b/database/update-v4.1.4.sql @@ -0,0 +1,12 @@ +CREATE TABLE `chatgpt_app_types` ( + `id` int NOT NULL, + `name` varchar(50) NOT NULL COMMENT '名称', + `icon` varchar(255) NOT NULL COMMENT '图标URL', + `sort_num` tinyint(3) NOT NULL COMMENT '排序', + `enabled` tinyint(1) NOT NULL COMMENT '是否启用', + `created_at` datetime NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='应用分类表'; + +ALTER TABLE `chatgpt_app_types`ADD PRIMARY KEY (`id`); +ALTER TABLE `chatgpt_app_types` MODIFY `id` int NOT NULL AUTO_INCREMENT; +ALTER TABLE `chatgpt_chat_roles` ADD `tid` INT NOT NULL COMMENT '分类ID' AFTER `name`; \ No newline at end of file diff --git a/web/src/views/ChatApps.vue b/web/src/views/ChatApps.vue index 48193f8e..45ab5677 100644 --- a/web/src/views/ChatApps.vue +++ b/web/src/views/ChatApps.vue @@ -64,7 +64,6 @@ import {arrayContains, removeArrayItem, substr} from "@/utils/libs"; import {useRouter} from "vue-router"; import {useSharedStore} from "@/store/sharedata"; import ItemList from "@/components/ItemList.vue"; -import {Plus} from "@element-plus/icons-vue"; const listBoxHeight = window.innerHeight - 87 const list = ref([]) @@ -72,7 +71,7 @@ const roles = ref([]) const store = useSharedStore(); onMounted(() => { - httpGet("/api/role/list").then((res) => { + httpGet("/api/app/list").then((res) => { const items = res.data // 处理 hello message for (let i = 0; i < items.length; i++) { @@ -112,7 +111,7 @@ const updateRole = (row, opt) => { } roles.value = removeArrayItem(roles.value, row.key) } - httpPost("/api/role/update", {keys: roles.value}).then(() => { + httpPost("/api/app/update", {keys: roles.value}).then(() => { ElMessage.success({message: title.value + "成功!", duration: 1000}) }).catch(e => { ElMessage.error(title.value + "失败:" + e.message) diff --git a/web/src/views/ChatPlus.vue b/web/src/views/ChatPlus.vue index 3552f5b9..48161be4 100644 --- a/web/src/views/ChatPlus.vue +++ b/web/src/views/ChatPlus.vue @@ -364,7 +364,7 @@ const initData = () => { modelID.value = models.value[0].id } // 加载角色列表 - httpGet(`/api/role/list`,{id:roleId.value}).then((res) => { + httpGet(`/api/app/list/user`,{id:roleId.value}).then((res) => { roles.value = res.data; if (!roleId.value) { roleId.value = roles.value[0]['id'] diff --git a/web/src/views/mobile/ChatList.vue b/web/src/views/mobile/ChatList.vue index a85af846..20864cf3 100644 --- a/web/src/views/mobile/ChatList.vue +++ b/web/src/views/mobile/ChatList.vue @@ -105,7 +105,7 @@ checkSession().then((user) => { loginUser.value = user isLogin.value = true // 加载角色列表 - httpGet(`/api/role/list`).then((res) => { + httpGet(`/api/app/list/user`).then((res) => { if (res.data) { const items = res.data for (let i = 0; i < items.length; i++) { @@ -139,7 +139,7 @@ checkSession().then((user) => { finished.value = true // 加载角色列表 - httpGet('/api/role/list').then((res) => { + httpGet('/api/app/list/user').then((res) => { if (res.data) { const items = res.data for (let i = 0; i < items.length; i++) { diff --git a/web/src/views/mobile/ChatSession.vue b/web/src/views/mobile/ChatSession.vue index f30db613..7a458bdd 100644 --- a/web/src/views/mobile/ChatSession.vue +++ b/web/src/views/mobile/ChatSession.vue @@ -186,7 +186,7 @@ httpGet('/api/model/list').then(res => { } modelValue.value = getModelName(modelId.value) // 加载角色列表 - httpGet(`/api/role/list`).then((res) => { + httpGet(`/api/app/list/user`).then((res) => { roles.value = res.data; if (!roleId.value) { roleId.value = roles.value[0]['id'] diff --git a/web/src/views/mobile/Index.vue b/web/src/views/mobile/Index.vue index 5ebd16a0..dd5430dd 100644 --- a/web/src/views/mobile/Index.vue +++ b/web/src/views/mobile/Index.vue @@ -109,7 +109,7 @@ onMounted(() => { }) const fetchApps = () => { - httpGet("/api/role/list").then((res) => { + httpGet("/api/app/list/user").then((res) => { const items = res.data // 处理 hello message for (let i = 0; i < items.length; i++) {