From a2cf97b039e7b34399daaff8b9a6218a2316666d Mon Sep 17 00:00:00 2001 From: RockYang Date: Mon, 10 Apr 2023 06:44:27 +0800 Subject: [PATCH] logout function is ready --- server/chat_handler.go | 4 ++++ server/server.go | 40 +++++++++++++++++++++++++++++--- web/public/images/user-info.jpg | Bin 0 -> 8583 bytes web/src/views/ChatPlus.vue | 14 +++++++++-- 4 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 web/public/images/user-info.jpg diff --git a/server/chat_handler.go b/server/chat_handler.go index 47547551..19929d41 100644 --- a/server/chat_handler.go +++ b/server/chat_handler.go @@ -42,6 +42,9 @@ func (s *Server) ChatHandle(c *gin.Context) { c.Abort() return } + // 保存会话连接 + s.ChatClients[sessionId] = client + // 加载历史消息,如果历史消息为空则发送打招呼消息 _, err = GetChatHistory(session.Username, roleKey) if err != nil { @@ -53,6 +56,7 @@ func (s *Server) ChatHandle(c *gin.Context) { if err != nil { logger.Error(err) client.Close() + delete(s.ChatClients, sessionId) return } diff --git a/server/server.go b/server/server.go index 716d1230..b0809c2e 100644 --- a/server/server.go +++ b/server/server.go @@ -39,9 +39,10 @@ type Server struct { // 保存 Websocket 会话 Username, 每个 Username 只能连接一次 // 防止第三方直接连接 socket 调用 OpenAI API - ChatSession map[string]types.ChatSession - ApiKeyAccessStat map[string]int64 // 记录每个 API Key 的最后访问之间,保持在 15/min 之内 - DebugMode bool // 是否开启调试模式 + ChatSession map[string]types.ChatSession //map[sessionId]User + ApiKeyAccessStat map[string]int64 // 记录每个 API Key 的最后访问之间,保持在 15/min 之内 + ChatClients map[string]*WsClient // Websocket 连接集合 + DebugMode bool // 是否开启调试模式 } func NewServer(configPath string) (*Server, error) { @@ -65,6 +66,7 @@ func NewServer(configPath string) (*Server, error) { ConfigPath: configPath, ChatContexts: make(map[string]types.ChatContext, 16), ChatSession: make(map[string]types.ChatSession), + ChatClients: make(map[string]*WsClient), ApiKeyAccessStat: make(map[string]int64), }, nil } @@ -84,6 +86,7 @@ func (s *Server) Run(webRoot embed.FS, path string, debug bool) { engine.POST("/test", s.TestHandle) engine.GET("/api/session/get", s.GetSessionHandle) engine.POST("/api/login", s.LoginHandle) + engine.POST("/api/logout", s.LogoutHandle) engine.Any("/api/chat", s.ChatHandle) engine.POST("api/chat/history", s.GetChatHistoryHandle) engine.POST("api/chat/history/clear", s.ClearHistoryHandle) @@ -307,3 +310,34 @@ func (s *Server) LoginHandle(c *gin.Context) { SessionId string `json:"session_id"` }{User: *user, SessionId: sessionId}}) } + +// LogoutHandle 注销 +func (s *Server) LogoutHandle(c *gin.Context) { + var data struct { + Opt string `json:"opt"` + } + err := json.NewDecoder(c.Request.Body).Decode(&data) + if err != nil { + c.JSON(http.StatusOK, types.BizVo{Code: types.Failed, Message: types.ErrorMsg}) + return + } + + if data.Opt == "logout" { + sessionId := c.GetHeader(types.TokenName) + session := sessions.Default(c) + session.Delete(sessionId) + err := session.Save() + if err != nil { + logger.Error("Error for save session: ", err) + } + // 删除 websocket 会话列表 + delete(s.ChatSession, sessionId) + // 关闭 socket 连接 + if client, ok := s.ChatClients[sessionId]; ok { + client.Close() + } + c.JSON(http.StatusOK, types.BizVo{Code: types.Success}) + } else { + c.JSON(http.StatusOK, types.BizVo{Code: types.Failed, Message: "Hack attempt!"}) + } +} diff --git a/web/public/images/user-info.jpg b/web/public/images/user-info.jpg new file mode 100644 index 0000000000000000000000000000000000000000..580598a1d137527fd7a1e6078480210ea030518d GIT binary patch literal 8583 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 s=CtX