From 8b14e141d0b4458002260656d68c60ef4b2c900d Mon Sep 17 00:00:00 2001 From: RockYang Date: Thu, 12 Oct 2023 10:02:12 +0800 Subject: [PATCH] opt: close websocket connection when finish a chat call for XunFei API --- api/handler/chatimpl/chat_history_handler.go | 103 ------------------- api/handler/chatimpl/chat_item_handler.go | 91 ++++++++++++++++ api/handler/chatimpl/xunfei_handler.go | 1 + api/test/test.go | 50 --------- web/src/views/ChatPlus.vue | 19 +++- 5 files changed, 106 insertions(+), 158 deletions(-) delete mode 100644 api/handler/chatimpl/chat_history_handler.go diff --git a/api/handler/chatimpl/chat_history_handler.go b/api/handler/chatimpl/chat_history_handler.go deleted file mode 100644 index 23d32ba4..00000000 --- a/api/handler/chatimpl/chat_history_handler.go +++ /dev/null @@ -1,103 +0,0 @@ -package chatimpl - -import ( - "chatplus/core/types" - "chatplus/store/model" - "chatplus/store/vo" - "chatplus/utils" - "chatplus/utils/resp" - "gorm.io/gorm" - - "github.com/gin-gonic/gin" -) - -// Update 更新会话标题 -func (h *ChatHandler) Update(c *gin.Context) { - var data struct { - Id uint `json:"id"` - Title string `json:"title"` - } - if err := c.ShouldBindJSON(&data); err != nil { - resp.ERROR(c, types.InvalidArgs) - return - } - var m = model.ChatItem{} - m.Id = data.Id - res := h.db.Model(&m).UpdateColumn("title", data.Title) - if res.Error != nil { - resp.ERROR(c, "Failed to update database") - return - } - - resp.SUCCESS(c, types.OkMsg) -} - -// History 获取聊天历史记录 -func (h *ChatHandler) History(c *gin.Context) { - chatId := c.Query("chat_id") // 会话 ID - var items []model.HistoryMessage - var messages = make([]vo.HistoryMessage, 0) - res := h.db.Where("chat_id = ?", chatId).Find(&items) - if res.Error != nil { - resp.ERROR(c, "No history message") - return - } else { - for _, item := range items { - var v vo.HistoryMessage - err := utils.CopyObject(item, &v) - v.CreatedAt = item.CreatedAt.Unix() - v.UpdatedAt = item.UpdatedAt.Unix() - if err == nil { - messages = append(messages, v) - } - } - } - - resp.SUCCESS(c, messages) -} - -// Clear 清空所有聊天记录 -func (h *ChatHandler) Clear(c *gin.Context) { - // 获取当前登录用户所有的聊天会话 - user, err := utils.GetLoginUser(c, h.db) - if err != nil { - resp.NotAuth(c) - return - } - - var chats []model.ChatItem - res := h.db.Where("user_id = ?", user.Id).Find(&chats) - if res.Error != nil { - resp.ERROR(c, "No chats found") - return - } - - var chatIds = make([]string, 0) - for _, chat := range chats { - chatIds = append(chatIds, chat.ChatId) - // 清空会话上下文 - h.App.ChatContexts.Delete(chat.ChatId) - } - err = h.db.Transaction(func(tx *gorm.DB) error { - res := h.db.Where("user_id =?", user.Id).Delete(&model.ChatItem{}) - if res.Error != nil { - return res.Error - } - - res = h.db.Where("user_id = ? AND chat_id IN ?", user.Id, chatIds).Delete(&model.HistoryMessage{}) - if res.Error != nil { - return res.Error - } - - // TODO: 是否要删除 MidJourney 绘画记录和图片文件? - return nil - }) - - if err != nil { - logger.Errorf("Error with delete chats: %+v", err) - resp.ERROR(c, "Failed to remove chat from database.") - return - } - - resp.SUCCESS(c, types.OkMsg) -} diff --git a/api/handler/chatimpl/chat_item_handler.go b/api/handler/chatimpl/chat_item_handler.go index e085e7e1..44af0a68 100644 --- a/api/handler/chatimpl/chat_item_handler.go +++ b/api/handler/chatimpl/chat_item_handler.go @@ -7,6 +7,7 @@ import ( "chatplus/utils" "chatplus/utils/resp" "github.com/gin-gonic/gin" + "gorm.io/gorm" ) // List 获取会话列表 @@ -47,6 +48,95 @@ func (h *ChatHandler) List(c *gin.Context) { resp.SUCCESS(c, items) } +// Update 更新会话标题 +func (h *ChatHandler) Update(c *gin.Context) { + var data struct { + ChatId string `json:"chat_id"` + Title string `json:"title"` + } + if err := c.ShouldBindJSON(&data); err != nil { + resp.ERROR(c, types.InvalidArgs) + return + } + res := h.db.Model(&model.ChatItem{}).Where("chat_id = ?", data.ChatId).UpdateColumn("title", data.Title) + if res.Error != nil { + resp.ERROR(c, "Failed to update database") + return + } + + resp.SUCCESS(c, types.OkMsg) +} + +// Clear 清空所有聊天记录 +func (h *ChatHandler) Clear(c *gin.Context) { + // 获取当前登录用户所有的聊天会话 + user, err := utils.GetLoginUser(c, h.db) + if err != nil { + resp.NotAuth(c) + return + } + + var chats []model.ChatItem + res := h.db.Where("user_id = ?", user.Id).Find(&chats) + if res.Error != nil { + resp.ERROR(c, "No chats found") + return + } + + var chatIds = make([]string, 0) + for _, chat := range chats { + chatIds = append(chatIds, chat.ChatId) + // 清空会话上下文 + h.App.ChatContexts.Delete(chat.ChatId) + } + err = h.db.Transaction(func(tx *gorm.DB) error { + res := h.db.Where("user_id =?", user.Id).Delete(&model.ChatItem{}) + if res.Error != nil { + return res.Error + } + + res = h.db.Where("user_id = ? AND chat_id IN ?", user.Id, chatIds).Delete(&model.HistoryMessage{}) + if res.Error != nil { + return res.Error + } + + // TODO: 是否要删除 MidJourney 绘画记录和图片文件? + return nil + }) + + if err != nil { + logger.Errorf("Error with delete chats: %+v", err) + resp.ERROR(c, "Failed to remove chat from database.") + return + } + + resp.SUCCESS(c, types.OkMsg) +} + +// History 获取聊天历史记录 +func (h *ChatHandler) History(c *gin.Context) { + chatId := c.Query("chat_id") // 会话 ID + var items []model.HistoryMessage + var messages = make([]vo.HistoryMessage, 0) + res := h.db.Where("chat_id = ?", chatId).Find(&items) + if res.Error != nil { + resp.ERROR(c, "No history message") + return + } else { + for _, item := range items { + var v vo.HistoryMessage + err := utils.CopyObject(item, &v) + v.CreatedAt = item.CreatedAt.Unix() + v.UpdatedAt = item.UpdatedAt.Unix() + if err == nil { + messages = append(messages, v) + } + } + } + + resp.SUCCESS(c, messages) +} + // Remove 删除会话 func (h *ChatHandler) Remove(c *gin.Context) { chatId := h.GetTrim(c, "chat_id") @@ -80,6 +170,7 @@ func (h *ChatHandler) Remove(c *gin.Context) { resp.SUCCESS(c, types.OkMsg) } +// Detail 对话详情,用户导出对话 func (h *ChatHandler) Detail(c *gin.Context) { chatId := h.GetTrim(c, "chat_id") if utils.IsEmptyValue(chatId) { diff --git a/api/handler/chatimpl/xunfei_handler.go b/api/handler/chatimpl/xunfei_handler.go index 156de4b7..5f1427e5 100644 --- a/api/handler/chatimpl/xunfei_handler.go +++ b/api/handler/chatimpl/xunfei_handler.go @@ -150,6 +150,7 @@ func (h *ChatHandler) sendXunFeiMessage( }) if result.Payload.Choices.Status == 2 { // 最终结果 + _ = conn.Close() // 关闭连接 break } diff --git a/api/test/test.go b/api/test/test.go index c0e85921..79058077 100644 --- a/api/test/test.go +++ b/api/test/test.go @@ -1,55 +1,5 @@ package main -import ( - "encoding/json" - "fmt" - "io" - "log" - "net/http" -) - func main() { - apiKey := "qjvqGdqpTY7qQaGBMenM7XgQ" - apiSecret := "3G1RzBGXywZv4VbYRTyAfNns1vIOAG8t" - token, err := getBaiduToken(apiKey, apiSecret) - if err != nil { - log.Fatal(err) - } - - fmt.Println(token) } - -func getBaiduToken(apiKey string, apiSecret string) (string, error) { - - url := fmt.Sprintf("https://aip.baidubce.com/oauth/2.0/token?client_id=%s&client_secret=%s&grant_type=client_credentials", apiKey, apiSecret) - client := &http.Client{} - req, err := http.NewRequest("POST", url, nil) - if err != nil { - return "", err - } - req.Header.Add("Content-Type", "application/json") - req.Header.Add("Accept", "application/json") - - res, err := client.Do(req) - if err != nil { - return "", fmt.Errorf("error with send request: %w", err) - } - defer res.Body.Close() - - body, err := io.ReadAll(res.Body) - if err != nil { - return "", fmt.Errorf("error with read response: %w", err) - } - var r map[string]interface{} - err = json.Unmarshal(body, &r) - if err != nil { - return "", fmt.Errorf("error with parse response: %w", err) - } - - if r["error"] != nil { - return "", fmt.Errorf("error with api response: %s", r["error_description"]) - } - - return fmt.Sprintf("%s", r["access_token"]), nil -} diff --git a/web/src/views/ChatPlus.vue b/web/src/views/ChatPlus.vue index c3974215..507296e7 100644 --- a/web/src/views/ChatPlus.vue +++ b/web/src/views/ChatPlus.vue @@ -22,7 +22,8 @@ @click="changeChat(chat)"> - + {{ chat.title }} @@ -451,16 +452,24 @@ const editChatTitle = function (event, chat) { tmpChatTitle.value = chat.title; }; + +const titleKeydown = (e, chat) => { + if (e.keyCode === 13) { + e.stopPropagation(); + confirm(e, chat) + } +} // 确认修改 const confirm = function (event, chat) { event.stopPropagation(); if (curOpt.value === 'edit') { if (tmpChatTitle.value === '') { - ElMessage.error("请输入会话标题!"); - return; + return ElMessage.error("请输入会话标题!"); } - - httpPost('/api/chat/update', {id: chat.id, title: tmpChatTitle.value}).then(() => { + if (!chat.chat_id) { + return ElMessage.error("对话 ID 为空,请刷新页面再试!"); + } + httpPost('/api/chat/update', {chat_id: chat.chat_id, title: tmpChatTitle.value}).then(() => { chat.title = tmpChatTitle.value; chat.edit = false; }).catch(e => {