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++) {