the function to save user chat history is ready

This commit is contained in:
RockYang 2023-04-19 17:32:41 +08:00
parent 14a351b477
commit a13c1bc669
9 changed files with 190 additions and 68 deletions

View File

@ -61,18 +61,18 @@ func (s *Server) ChatHandle(c *gin.Context) {
return
}
logger.Info("Receive a message: ", string(message))
//replyMessage(client, "当前 TOKEN 无效,请使用合法的 TOKEN 登录!", false)
replyMessage(client, "当前 TOKEN 无效,请使用合法的 TOKEN 登录!", false)
//replyMessage(client, "![](images/wx.png)", true)
ctx, cancel := context.WithCancel(context.Background())
s.ReqCancelFunc[sessionId] = cancel
// 回复消息
err = s.sendMessage(ctx, session, chatRole, string(message), client, false)
if err != nil {
logger.Error(err)
} else {
replyChunkMessage(client, types.WsMessage{Type: types.WsEnd, IsHelloMsg: false})
logger.Info("回答完毕: " + string(message))
}
//ctx, cancel := context.WithCancel(context.Background())
//s.ReqCancelFunc[sessionId] = cancel
//// 回复消息
//err = s.sendMessage(ctx, session, chatRole, string(message), client, false)
//if err != nil {
// logger.Error(err)
//} else {
// replyChunkMessage(client, types.WsMessage{Type: types.WsEnd, IsHelloMsg: false})
// logger.Info("回答完毕: " + string(message))
//}
}
}()

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -62,7 +62,7 @@ export default defineComponent({
.content {
word-break break-word;
padding: 5px 10px;
padding: 6px 10px;
background-color: #98E165;
color var(--content-color);
font-size: var(--content-font-size);

View File

@ -97,7 +97,7 @@ export default defineComponent({
.content {
min-height 20px;
word-break break-word;
padding: 8px 10px;
padding: 6px 10px;
color var(--content-color)
background-color: #fff;
font-size: var(--content-font-size);

View File

@ -34,7 +34,7 @@ const routes = [
},
{
name: 'free', path: '/free', component: ChatFree, meta: {
title: 'ChatGPT 通用免费版'
title: '【文心一言】免费版'
}
},
{

View File

@ -7,7 +7,8 @@ import Storage from 'good-storage'
*/
const SessionUserKey = 'LOGIN_USER';
const ChatHistoryKey = "CHAT_HISTORY";
const ChatHistoryKey = 'CHAT_HISTORY';
const ChatListKey = 'CHAT_LIST';
export function getSessionId() {
const user = getLoginUser();
@ -55,8 +56,32 @@ export function appendChatHistory(chatId, message) {
// 获取指定会话的历史记录
export function getChatHistory(chatId) {
const history = Storage.get(ChatHistoryKey);
if (history && history[chatId]) {
return history[chatId];
if (!history) {
return null;
}
return [];
return history[chatId] ? history[chatId] : null;
}
export function getChatList() {
return Storage.get(ChatListKey);
}
export function getChat(chatId) {
let chatList = Storage.get(ChatListKey);
if (!chatList) {
return null;
}
return chatList[chatId] ? chatList[chatId] : null;
}
export function setChat(chat) {
let chatList = Storage.get(ChatListKey);
if (!chatList) {
chatList = {};
}
chatList[chat.id] = chat;
Storage.set(ChatListKey, chatList);
}

View File

@ -252,7 +252,6 @@ export default defineComponent({
id: randString(32),
icon: this.replyIcon,
content: "",
cursor: true
});
if (data['is_hello_msg'] !== true) {
this.canReGenerate = true;

View File

@ -2,13 +2,21 @@
<div class="chat-free-page">
<div class="sidebar" id="sidebar">
<nav>
<ul>
<li class="new-chat" @click="newChat"><a>
<div class="new-chat" @click="newChat">
<a>
<span class="icon"><el-icon><Plus/></el-icon></span>
<span class="text">新建会话</span>
<span class="btn" @click="toggleSidebar"><el-button size="small" type="info" circle><el-icon><CloseBold/></el-icon></el-button></span>
</a></li>
<li v-for="chat in chatList" :key="chat.id"><a>
</a>
</div>
<ul>
<!-- <li class="new-chat" @click="newChat"><a>-->
<!-- <span class="icon"><el-icon><Plus/></el-icon></span>-->
<!-- <span class="text">新建会话</span>-->
<!-- <span class="btn" @click="toggleSidebar"><el-button size="small" type="info" circle><el-icon><CloseBold/></el-icon></el-button></span>-->
<!-- </a></li>-->
<li v-for="chat in chatList" :key="chat.id" @click="changeChat(chat)" :class="chat.active ? 'active' : ''"><a>
<span class="icon"><el-icon><ChatRound/></el-icon></span>
<span class="text" v-if="chat.edit">
@ -47,7 +55,7 @@
:icon="chat.icon"
:content="chat.content"/>
<chat-reply v-else-if="chat.type==='reply'"
:icon="chat.icon"
:icon="replyIcon"
:org-content="chat.orgContent"
:content="chat.content"/>
</div>
@ -146,7 +154,15 @@ import {httpGet, httpPost} from "@/utils/http";
import hl from "highlight.js";
import ChatReply from "@/components/ChatReply.vue";
import ChatPrompt from "@/components/ChatPrompt.vue";
import {getSessionId, getUserInfo, setLoginUser} from "@/utils/storage";
import {
setChat,
appendChatHistory,
getChatHistory,
getChatList,
getSessionId,
getUserInfo,
setLoginUser
} from "@/utils/storage";
import {ElMessage, ElMessageBox} from "element-plus";
import {isMobile, randString} from "@/utils/libs";
import Clipboard from "clipboard";
@ -177,12 +193,13 @@ export default defineComponent({
userInfo: {},
showLoginDialog: false,
role: 'gpt',
replyIcon: 'images/avatar/gpt.png', //
replyIcon: 'images/avatar/yi_yan.png', //
chatList: [], //
tmpChatTitle: '',
curOpt: '', //
curChat: null, //
curPrompt: null, //
showStopGenerate: false,
showReGenerate: false,
@ -202,8 +219,6 @@ export default defineComponent({
},
mounted() {
this.fetchChatHistory();
const clipboard = new Clipboard('.copy-reply');
clipboard.on('success', () => {
ElMessage.success('复制成功!');
@ -229,7 +244,7 @@ export default defineComponent({
}
});
this.connect();
this.newChat();
},
@ -256,7 +271,6 @@ export default defineComponent({
this.errorMessage.close(); //
}
this.activelyClose = false;
// this.chatList.push(this.curChat);
//
this.fetchChatHistory();
});
@ -273,7 +287,6 @@ export default defineComponent({
id: randString(32),
icon: this.replyIcon,
content: "",
cursor: true
});
if (data['is_hello_msg'] !== true) {
this.canReGenerate = true;
@ -282,9 +295,19 @@ export default defineComponent({
this.sending = false;
if (data['is_hello_msg'] !== true) {
this.showReGenerate = true;
//
appendChatHistory(this.curChat.id, this.curPrompt);
appendChatHistory(this.curChat.id, {
type: "reply",
id: randString(32),
icon: this.replyIcon,
content: this.lineBuffer,
})
}
this.showStopGenerate = false;
this.lineBuffer = ''; //
} else {
this.lineBuffer += data.content;
this.chatData[this.chatData.length - 1]['orgContent'] = this.lineBuffer;
@ -350,21 +373,21 @@ export default defineComponent({
//
fetchChatHistory: function () {
httpPost("/api/chat/history", {role: this.role}).then((res) => {
if (this.chatData.length > 0) { //
return
}
const chatList = getChatList();
if (chatList) {
this.chatList = chatList;
const data = res.data
const list = getChatHistory(this.curChat.id);
if (list) {
const md = require('markdown-it')();
for (let i = 0; i < data.length; i++) {
if (data[i].type === "prompt") {
this.chatData.push(data[i]);
for (let i = 0; i < list.length; i++) {
if (list[i].type === "prompt") {
this.chatData.push(list[i]);
continue;
}
data[i].orgContent = data[i].content;
data[i].content = md.render(data[i].content);
this.chatData.push(data[i]);
list[i].orgContent = list[i].content;
list[i].content = md.render(list[i].content);
this.chatData.push(list[i]);
}
nextTick(() => {
@ -374,9 +397,10 @@ export default defineComponent({
hl.highlightElement(block)
})
})
}).catch(() => {
// console.error(e.message)
})
}
}
},
inputKeyDown: function (e) {
@ -405,12 +429,13 @@ export default defineComponent({
}
//
this.chatData.push({
this.curPrompt = {
type: "prompt",
id: randString(32),
icon: 'images/avatar/user.png',
content: this.inputValue
});
};
this.chatData.push(this.curPrompt);
this.sending = true;
this.showStopGenerate = true;
@ -510,14 +535,25 @@ export default defineComponent({
//
newChat: function () {
//
if (this.curChat !== null) {
const chatHistory = getChatHistory(this.curChat.id);
if (chatHistory === null) {
return;
}
//
setChat(this.curChat);
}
this.curChat = {
id: randString(32),
edit: false, //
removing: false, //
title: '新会话 - ' + this.chatList.length
active: false,
title: '新会话 - 0'
};
//
this.chatData = [];
this.connect();
},
@ -533,6 +569,7 @@ export default defineComponent({
if (this.curOpt === 'edit') {
chat.title = this.tmpChatTitle;
chat.edit = false;
setChat(chat)
} else if (this.curOpt === 'remove') {
for (let i = 0; i < this.chatList.length; i++) {
if (this.chatList[i].id === chat.id) {
@ -551,8 +588,23 @@ export default defineComponent({
removeChat: function (chat) {
chat.removing = true;
this.curOpt = 'remove';
},
//
changeChat: function (chat) {
if (this.curChat.id === chat.id) {
return;
}
this.curChat.active = false;
chat.active = true;
this.curChat = chat;
const chatHistory = getChatHistory(chat.id);
if (!chatHistory) {
return;
}
this.chatData = chatHistory;
}
}
})
@ -574,10 +626,51 @@ export default defineComponent({
margin 0
padding 0
width 100%
height calc(100vh - 150px)
border 1px solid red;
overflow-y auto
.new-chat {
position fixed;
color: #ffffff
padding 10px;
cursor pointer
&:hover {
background-color #3E3F49
a {
.btn {
display block
background-color: #3E3F49;
}
}
}
a {
border: 1px solid #4A4B4D;
box-sizing: border-box;
border-radius 5px;
width 100%;
display flex;
padding 10px;
.btn {
display none
right -2px;
top -2px;
.el-icon {
margin-left 0;
color #ffffff
}
}
}
}
ul {
list-style-type: none
padding 5px
padding 50px 5px 5px 5px
margin 0
li {
@ -589,12 +682,12 @@ export default defineComponent({
border-radius 5px;
&:hover {
background-color #2E2F39
background-color #3E3F49
a {
.btn {
display block
background-color: #282A32;
background-color: #3E3F49;
}
}
}
@ -647,7 +740,7 @@ export default defineComponent({
}
li.active {
background-color #2E2F39
background-color #3E3F49
}
li.new-chat {
@ -669,6 +762,11 @@ export default defineComponent({
}
}
nav::-webkit-scrollbar {
width: 0;
height: 0;
}
}
.main-content {
@ -707,6 +805,7 @@ export default defineComponent({
justify-content flex-start
.chat-box {
width 100%;
padding: 10px;
overflow-y: auto;
height: calc(100vh - 80px);

View File

@ -329,8 +329,7 @@ export default defineComponent({
type: "reply",
id: randString(32),
icon: this.replyIcon,
content: "",
cursor: true
content: ""
});
if (data['is_hello_msg'] !== true) {
this.canReGenerate = true;