diff --git a/README.md b/README.md
index 61622b89..cdcc1bce 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
## TODOLIST
-* [ ] 使用 level DB 保存用户聊天记录
+* [x] 使用 level DB 保存用户聊天记录
* [x] 用户聊天鉴权,设置口令模式
* [ ] 定期清理不在线的会话 sessionID 和聊天上下文记录
* [x] 给 Token 设置调用次数
diff --git a/server/chat_handler.go b/server/chat_handler.go
index 42362e77..617a4885 100644
--- a/server/chat_handler.go
+++ b/server/chat_handler.go
@@ -341,3 +341,25 @@ func (s *Server) GetChatHistoryHandle(c *gin.Context) {
c.JSON(http.StatusOK, types.BizVo{Code: types.Success, Data: messages})
}
+
+// ClearHistoryHandle 清空聊天记录
+func (s *Server) ClearHistoryHandle(c *gin.Context) {
+ sessionId := c.GetHeader(types.TokenName)
+ var data struct {
+ Role string `json:"role"`
+ }
+ err := json.NewDecoder(c.Request.Body).Decode(&data)
+ if err != nil {
+ c.JSON(http.StatusOK, types.BizVo{Code: types.Failed, Message: "Invalid args"})
+ return
+ }
+
+ session := s.ChatSession[sessionId]
+ err = ClearChatHistory(session.Username, data.Role)
+ if err != nil {
+ c.JSON(http.StatusOK, types.BizVo{Code: types.Failed, Message: "Failed to remove data from DB"})
+ return
+ }
+
+ c.JSON(http.StatusOK, types.BizVo{Code: types.Success})
+}
diff --git a/server/config_handler.go b/server/config_handler.go
index 1b96c984..40512288 100644
--- a/server/config_handler.go
+++ b/server/config_handler.go
@@ -291,6 +291,7 @@ func (s *Server) GetChatRoleListHandle(c *gin.Context) {
})
}
}
+
c.JSON(http.StatusOK, types.BizVo{Code: types.Success, Message: types.OkMsg, Data: res})
}
diff --git a/server/server.go b/server/server.go
index 5576bfa1..125e6ab0 100644
--- a/server/server.go
+++ b/server/server.go
@@ -83,6 +83,7 @@ func (s *Server) Run(webRoot embed.FS, path string, debug bool) {
engine.POST("/api/login", s.LoginHandle)
engine.Any("/api/chat", s.ChatHandle)
engine.POST("api/chat/history", s.GetChatHistoryHandle)
+ engine.POST("api/chat/history/clear", s.ClearHistoryHandle)
engine.POST("/api/config/set", s.ConfigSetHandle)
engine.GET("/api/config/chat-roles/get", s.GetChatRoleListHandle)
@@ -157,7 +158,7 @@ func corsMiddleware() gin.HandlerFunc {
c.Header("Access-Control-Allow-Origin", origin)
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
//允许跨域设置可以返回其他子段,可以自定义字段
- c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, Content-Type, ChatGPT-Username")
+ c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, Content-Type, ChatGPT-TOKEN")
// 允许浏览器(客户端)可以解析的头部 (重要)
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
//设置缓存时间
diff --git a/web/src/views/Chat.vue b/web/src/views/Chat.vue
index 1b740380..249b380f 100644
--- a/web/src/views/Chat.vue
+++ b/web/src/views/Chat.vue
@@ -3,7 +3,7 @@
- 欢迎来到人工智能时代
+
@@ -14,6 +14,12 @@
:value="item.key"
/>
+
+
+
+
+
+
@@ -89,7 +95,7 @@ import ChatPrompt from "@/components/ChatPrompt.vue";
import ChatReply from "@/components/ChatReply.vue";
import {randString} from "@/utils/libs";
import {ElMessage, ElMessageBox} from 'element-plus'
-import {Tools, Lock} from '@element-plus/icons-vue'
+import {Tools, Lock, Delete} from '@element-plus/icons-vue'
import ConfigDialog from '@/components/ConfigDialog.vue'
import {httpPost, httpGet} from "@/utils/http";
import {getSessionId, setSessionId} from "@/utils/storage";
@@ -98,7 +104,7 @@ import 'highlight.js/styles/a11y-dark.css'
export default defineComponent({
name: "XChat",
- components: {ChatPrompt, ChatReply, Tools, Lock, ConfigDialog},
+ components: {ChatPrompt, ChatReply, Tools, Lock, Delete, ConfigDialog},
data() {
return {
title: 'ChatGPT 控制台',
@@ -118,7 +124,7 @@ export default defineComponent({
socket: null,
toolBoxHeight: 61 + 42, // 工具框的高度
inputBoxWidth: window.innerWidth - 20,
- sending: true,
+ sending: false,
loading: false
}
},
@@ -189,9 +195,6 @@ export default defineComponent({
});
this.connect();
-
- this.fetchChatHistory();
-
},
methods: {
@@ -203,13 +206,16 @@ export default defineComponent({
socket.addEventListener('open', () => {
// 获取聊天角色
httpGet("/api/config/chat-roles/get").then((res) => {
- ElMessage.success('创建会话成功!');
+ // ElMessage.success('创建会话成功!');
this.chatRoles = res.data;
this.loading = false
}).catch(() => {
ElMessage.error("获取聊天角色失败");
})
+ // 加载聊天记录
+ this.fetchChatHistory();
+
if (this.connectingMessageBox && typeof this.connectingMessageBox.close === 'function') {
this.connectingMessageBox.close();
this.connectingMessageBox = null;
@@ -303,16 +309,33 @@ export default defineComponent({
break;
}
}
-
- this.fetchChatHistory();
},
// 从后端获取聊天历史记录
fetchChatHistory: function () {
httpPost("/api/chat/history", {role: this.role}).then((res) => {
- this.chatData = res.data
- }).catch((e) => {
- console.error(e.message)
+ const data = res.data
+ const md = require('markdown-it')();
+ for (let i = 0; i < data.length; i++) {
+ if (data[i].type === "prompt") {
+ this.chatData.push(data[i]);
+ continue;
+ }
+
+ data[i].content = md.render(data[i].content);
+ this.chatData.push(data[i]);
+ }
+
+ nextTick(() => {
+ hl.configure({ignoreUnescapedHTML: true})
+ const lines = document.querySelectorAll('.chat-line');
+ const blocks = lines[lines.length - 1].querySelectorAll('pre code');
+ blocks.forEach((block) => {
+ hl.highlightElement(block)
+ })
+ })
+ }).catch(() => {
+ // console.error(e.message)
})
},
@@ -390,6 +413,31 @@ export default defineComponent({
if (e.keyCode === 13) {
this.submitToken();
}
+ },
+
+ // 清空聊天记录
+ clearChatHistory: function () {
+ ElMessageBox.confirm(
+ '确认要清空当前角色聊天历史记录吗?
此操作不可以撤销!',
+ '操作提示:',
+ {
+ confirmButtonText: '确认',
+ cancelButtonText: '取消',
+ type: 'warning',
+ dangerouslyUseHTMLString: true,
+ showClose: true,
+ closeOnClickModal: false,
+ center: true,
+ }
+ ).then(() => {
+ httpPost("/api/chat/history/clear", {role: this.role}).then(() => {
+ ElMessage.success("当前角色会话已清空");
+ this.chatData = [];
+ }).catch(() => {
+ ElMessage.error("删除失败")
+ })
+ }).catch(() => {
+ })
}
},
@@ -418,7 +466,7 @@ export default defineComponent({
align-items center;
.el-select {
- max-width 150px;
+ max-width 120px;
}
.chat-role {
@@ -428,6 +476,10 @@ export default defineComponent({
.el-image {
margin-right 5px;
}
+
+ .clear-history {
+ margin-left 5px;
+ }
}
.chat-box {