mirror of
				https://github.com/yangjian102621/geekai.git
				synced 2025-11-04 16:23:42 +08:00 
			
		
		
		
	优化用户聊天记录显示
This commit is contained in:
		@@ -4,7 +4,7 @@
 | 
			
		||||
 | 
			
		||||
## TODOLIST
 | 
			
		||||
 | 
			
		||||
* [ ] 使用 level DB 保存用户聊天记录
 | 
			
		||||
* [x] 使用 level DB 保存用户聊天记录
 | 
			
		||||
* [x] 用户聊天鉴权,设置口令模式
 | 
			
		||||
* [ ] 定期清理不在线的会话 sessionID 和聊天上下文记录
 | 
			
		||||
* [x] 给 Token 设置调用次数
 | 
			
		||||
 
 | 
			
		||||
@@ -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})
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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")
 | 
			
		||||
			//设置缓存时间
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
    <div id="container">
 | 
			
		||||
      <div class="tool-box">
 | 
			
		||||
        <el-image style="width: 24px; height: 24px" :src="logo"/>
 | 
			
		||||
        <el-button round>欢迎来到人工智能时代</el-button>
 | 
			
		||||
        <!--        <el-button round>WeChatGPT</el-button>-->
 | 
			
		||||
        <el-select v-model="role" class="chat-role"
 | 
			
		||||
                   v-on:change="changeRole"
 | 
			
		||||
                   placeholder="请选择对话角色">
 | 
			
		||||
@@ -14,6 +14,12 @@
 | 
			
		||||
              :value="item.key"
 | 
			
		||||
          />
 | 
			
		||||
        </el-select>
 | 
			
		||||
 | 
			
		||||
        <el-button type="danger" class="clear-history" size="small" circle @click="clearChatHistory">
 | 
			
		||||
          <el-icon>
 | 
			
		||||
            <Delete/>
 | 
			
		||||
          </el-icon>
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div class="chat-box" id="chat-box" :style="{height: chatBoxHeight+'px'}">
 | 
			
		||||
@@ -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(
 | 
			
		||||
          '确认要清空当前角色聊天历史记录吗?<br/>此操作不可以撤销!',
 | 
			
		||||
          '操作提示:',
 | 
			
		||||
          {
 | 
			
		||||
            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 {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user