mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-09-18 01:06:39 +08:00
在进行 socket 连接前先关闭之前连接。实现新建会话功能。
This commit is contained in:
parent
50ff591dbb
commit
14a351b477
@ -290,6 +290,17 @@ func (s *Server) RemoveUserHandle(c *gin.Context) {
|
|||||||
|
|
||||||
// GetUserListHandle 获取用户列表
|
// GetUserListHandle 获取用户列表
|
||||||
func (s *Server) GetUserListHandle(c *gin.Context) {
|
func (s *Server) GetUserListHandle(c *gin.Context) {
|
||||||
|
username := c.PostForm("username")
|
||||||
|
if username != "" {
|
||||||
|
user, err := GetUser(username)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusOK, types.BizVo{Code: types.Failed, Message: "User not exists"})
|
||||||
|
} else {
|
||||||
|
c.JSON(http.StatusOK, types.BizVo{Code: types.Success, Message: types.OkMsg, Data: user})
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, types.BizVo{Code: types.Success, Message: types.OkMsg, Data: GetUsers()})
|
c.JSON(http.StatusOK, types.BizVo{Code: types.Success, Message: types.OkMsg, Data: GetUsers()})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ func (s *Server) Run(webRoot embed.FS, path string, debug bool) {
|
|||||||
for {
|
for {
|
||||||
for key, ctx := range s.ChatContexts {
|
for key, ctx := range s.ChatContexts {
|
||||||
// 清理超过 60min 没有更新,则表示为过期会话
|
// 清理超过 60min 没有更新,则表示为过期会话
|
||||||
if time.Now().Unix()-ctx.LastAccessTime > int64(s.Config.Chat.ChatContextExpireTime) {
|
if time.Now().Unix()-ctx.LastAccessTime >= int64(s.Config.Chat.ChatContextExpireTime) {
|
||||||
logger.Infof("清理会话上下文: %s", key)
|
logger.Infof("清理会话上下文: %s", key)
|
||||||
delete(s.ChatContexts, key)
|
delete(s.ChatContexts, key)
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package utils
|
|||||||
import (
|
import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,10 +26,6 @@ func Long2IP(ipInt int64) string {
|
|||||||
return b0 + "." + b1 + "." + b2 + "." + b3
|
return b0 + "." + b1 + "." + b2 + "." + b3
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsBlank(value string) bool {
|
|
||||||
return len(strings.TrimSpace(value)) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func ContainsStr(slice []string, item string) bool {
|
func ContainsStr(slice []string, item string) bool {
|
||||||
for _, e := range slice {
|
for _, e := range slice {
|
||||||
if e == item {
|
if e == item {
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
class="box-item"
|
class="box-item"
|
||||||
effect="dark"
|
effect="dark"
|
||||||
content="复制回答"
|
content="复制回答"
|
||||||
placement="top"
|
placement="bottom"
|
||||||
>
|
>
|
||||||
<el-button type="info" class="copy-reply" :data-clipboard-text="orgContent" plain>
|
<el-button type="info" class="copy-reply" :data-clipboard-text="orgContent" plain>
|
||||||
<el-icon>
|
<el-icon>
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
/* eslint-disable no-constant-condition */
|
/* eslint-disable no-constant-condition */
|
||||||
import {dateFormat} from "@/utils/libs";
|
import {dateFormat} from "@/utils/libs";
|
||||||
|
import Storage from 'good-storage'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* storage handler
|
* storage handler
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const SessionUserKey = 'LOGIN_USER';
|
const SessionUserKey = 'LOGIN_USER';
|
||||||
export const Global = {}
|
const ChatHistoryKey = "CHAT_HISTORY";
|
||||||
|
|
||||||
export function getSessionId() {
|
export function getSessionId() {
|
||||||
const user = getLoginUser();
|
const user = getLoginUser();
|
||||||
@ -36,3 +37,26 @@ export function getUserInfo() {
|
|||||||
}
|
}
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 追加历史记录
|
||||||
|
export function appendChatHistory(chatId, message) {
|
||||||
|
let history = Storage.get(ChatHistoryKey);
|
||||||
|
if (!history) {
|
||||||
|
history = {};
|
||||||
|
}
|
||||||
|
if (!history[chatId]) {
|
||||||
|
history[chatId] = [message];
|
||||||
|
} else {
|
||||||
|
history[chatId].push(message);
|
||||||
|
}
|
||||||
|
Storage.set(ChatHistoryKey, history);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取指定会话的历史记录
|
||||||
|
export function getChatHistory(chatId) {
|
||||||
|
const history = Storage.get(ChatHistoryKey);
|
||||||
|
if (history && history[chatId]) {
|
||||||
|
return history[chatId];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
@ -208,6 +208,12 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
// 创建 socket 会话连接
|
// 创建 socket 会话连接
|
||||||
connect: function () {
|
connect: function () {
|
||||||
|
// 先关闭已有连接
|
||||||
|
if (this.socket !== null) {
|
||||||
|
this.activelyClose = true;
|
||||||
|
this.socket.close();
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化 WebSocket 对象
|
// 初始化 WebSocket 对象
|
||||||
const sessionId = getSessionId();
|
const sessionId = getSessionId();
|
||||||
const socket = new WebSocket(process.env.VUE_APP_WS_HOST + `/api/chat?sessionId=${sessionId}&role=${this.role}`);
|
const socket = new WebSocket(process.env.VUE_APP_WS_HOST + `/api/chat?sessionId=${sessionId}&role=${this.role}`);
|
||||||
@ -226,6 +232,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.sending = false; // 允许用户发送消息
|
this.sending = false; // 允许用户发送消息
|
||||||
|
this.activelyClose = false;
|
||||||
if (this.errorMessage !== null) {
|
if (this.errorMessage !== null) {
|
||||||
this.errorMessage.close(); // 关闭错误提示信息
|
this.errorMessage.close(); // 关闭错误提示信息
|
||||||
}
|
}
|
||||||
@ -282,6 +289,10 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
|
|
||||||
socket.addEventListener('close', () => {
|
socket.addEventListener('close', () => {
|
||||||
|
if (this.activelyClose) { // 忽略主动关闭
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 停止送消息
|
// 停止送消息
|
||||||
this.sending = true;
|
this.sending = true;
|
||||||
this.checkSession();
|
this.checkSession();
|
||||||
|
@ -8,13 +8,23 @@
|
|||||||
<span class="text">新建会话</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>
|
<span class="btn" @click="toggleSidebar"><el-button size="small" type="info" circle><el-icon><CloseBold/></el-icon></el-button></span>
|
||||||
</a></li>
|
</a></li>
|
||||||
<li v-for="session in sessionList" :key="session.id"><a>
|
<li v-for="chat in chatList" :key="chat.id"><a>
|
||||||
<span class="icon"><el-icon><ChatRound/></el-icon></span>
|
<span class="icon"><el-icon><ChatRound/></el-icon></span>
|
||||||
<span class="text">{{ session.title }}</span>
|
|
||||||
<span class="btn">
|
<span class="text" v-if="chat.edit">
|
||||||
<el-icon title="编辑"><Edit/></el-icon>
|
<el-input v-model="tmpChatTitle" size="small" placeholder="请输入会话标题"/>
|
||||||
<el-icon title="删除会话"><Delete/></el-icon>
|
|
||||||
</span>
|
</span>
|
||||||
|
<span class="text" v-else>{{ chat.title }}</span>
|
||||||
|
|
||||||
|
<span class="btn btn-check" v-if="chat.edit || chat.removing">
|
||||||
|
<el-icon @click="confirm(chat)"><Check/></el-icon>
|
||||||
|
<el-icon @click="cancel(chat)"><Close/></el-icon>
|
||||||
|
</span>
|
||||||
|
<span class="btn" v-else>
|
||||||
|
<el-icon title="编辑" @click="editChatTitle(chat)"><Edit/></el-icon>
|
||||||
|
<el-icon title="删除会话" @click="removeChat(chat)"><Delete/></el-icon>
|
||||||
|
</span>
|
||||||
|
|
||||||
</a></li>
|
</a></li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
@ -123,7 +133,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import {defineComponent, nextTick} from "vue"
|
import {defineComponent, nextTick} from "vue"
|
||||||
import {
|
import {
|
||||||
ChatRound,
|
ChatRound, Check, Close,
|
||||||
CloseBold,
|
CloseBold,
|
||||||
Delete, Edit,
|
Delete, Edit,
|
||||||
Fold,
|
Fold,
|
||||||
@ -145,6 +155,8 @@ import Clipboard from "clipboard";
|
|||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'ChatFree',
|
name: 'ChatFree',
|
||||||
components: {
|
components: {
|
||||||
|
Close,
|
||||||
|
Check,
|
||||||
Edit,
|
Edit,
|
||||||
Delete,
|
Delete,
|
||||||
CloseBold,
|
CloseBold,
|
||||||
@ -166,10 +178,11 @@ export default defineComponent({
|
|||||||
showLoginDialog: false,
|
showLoginDialog: false,
|
||||||
role: 'gpt',
|
role: 'gpt',
|
||||||
replyIcon: 'images/avatar/gpt.png', // 回复信息的头像
|
replyIcon: 'images/avatar/gpt.png', // 回复信息的头像
|
||||||
sessionList: [{
|
|
||||||
id: randString(32),
|
chatList: [], // 会话列表
|
||||||
title: '响应式页面布局代码'
|
tmpChatTitle: '',
|
||||||
}], // 会话列表
|
curOpt: '', // 当前操作
|
||||||
|
curChat: null, // 当前会话
|
||||||
|
|
||||||
showStopGenerate: false,
|
showStopGenerate: false,
|
||||||
showReGenerate: false,
|
showReGenerate: false,
|
||||||
@ -180,6 +193,7 @@ export default defineComponent({
|
|||||||
lineBuffer: '', // 输出缓冲行
|
lineBuffer: '', // 输出缓冲行
|
||||||
errorMessage: null, // 错误信息提示框
|
errorMessage: null, // 错误信息提示框
|
||||||
socket: null,
|
socket: null,
|
||||||
|
activelyClose: false, // 主动关闭
|
||||||
inputBoxWidth: 0,
|
inputBoxWidth: 0,
|
||||||
sending: true,
|
sending: true,
|
||||||
loading: true,
|
loading: true,
|
||||||
@ -226,6 +240,12 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
// 创建 socket 会话连接
|
// 创建 socket 会话连接
|
||||||
connect: function () {
|
connect: function () {
|
||||||
|
// 先关闭已有连接
|
||||||
|
if (this.socket !== null) {
|
||||||
|
this.activelyClose = true;
|
||||||
|
this.socket.close();
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化 WebSocket 对象
|
// 初始化 WebSocket 对象
|
||||||
const sessionId = getSessionId();
|
const sessionId = getSessionId();
|
||||||
const socket = new WebSocket(process.env.VUE_APP_WS_HOST + `/api/chat?sessionId=${sessionId}&role=${this.role}`);
|
const socket = new WebSocket(process.env.VUE_APP_WS_HOST + `/api/chat?sessionId=${sessionId}&role=${this.role}`);
|
||||||
@ -235,6 +255,8 @@ export default defineComponent({
|
|||||||
if (this.errorMessage !== null) {
|
if (this.errorMessage !== null) {
|
||||||
this.errorMessage.close(); // 关闭错误提示信息
|
this.errorMessage.close(); // 关闭错误提示信息
|
||||||
}
|
}
|
||||||
|
this.activelyClose = false;
|
||||||
|
// this.chatList.push(this.curChat);
|
||||||
// 加载聊天记录
|
// 加载聊天记录
|
||||||
this.fetchChatHistory();
|
this.fetchChatHistory();
|
||||||
});
|
});
|
||||||
@ -288,6 +310,10 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
|
|
||||||
socket.addEventListener('close', () => {
|
socket.addEventListener('close', () => {
|
||||||
|
if (this.activelyClose) { // 忽略主动关闭
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 停止送消息
|
// 停止送消息
|
||||||
this.sending = true;
|
this.sending = true;
|
||||||
this.checkSession();
|
this.checkSession();
|
||||||
@ -484,8 +510,50 @@ export default defineComponent({
|
|||||||
|
|
||||||
// 新建会话
|
// 新建会话
|
||||||
newChat: function () {
|
newChat: function () {
|
||||||
|
this.curChat = {
|
||||||
|
id: randString(32),
|
||||||
|
edit: false, // 是否处于编辑模式
|
||||||
|
removing: false, // 是否处于删除模式
|
||||||
|
title: '新会话 - ' + this.chatList.length
|
||||||
|
};
|
||||||
|
|
||||||
|
// 连接会话
|
||||||
|
this.connect();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 编辑会话标题
|
||||||
|
editChatTitle: function (chat) {
|
||||||
|
chat.edit = true;
|
||||||
|
this.curOpt = 'edit';
|
||||||
|
this.tmpChatTitle = chat.title;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 确认修改
|
||||||
|
confirm: function (chat) {
|
||||||
|
if (this.curOpt === 'edit') {
|
||||||
|
chat.title = this.tmpChatTitle;
|
||||||
|
chat.edit = false;
|
||||||
|
} else if (this.curOpt === 'remove') {
|
||||||
|
for (let i = 0; i < this.chatList.length; i++) {
|
||||||
|
if (this.chatList[i].id === chat.id) {
|
||||||
|
this.chatList.remove(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
cancel: function (chat) {
|
||||||
|
chat.edit = false;
|
||||||
|
chat.removing = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除会话
|
||||||
|
removeChat: function (chat) {
|
||||||
|
chat.removing = true;
|
||||||
|
this.curOpt = 'remove';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@ -522,6 +590,13 @@ export default defineComponent({
|
|||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color #2E2F39
|
background-color #2E2F39
|
||||||
|
|
||||||
|
a {
|
||||||
|
.btn {
|
||||||
|
display block
|
||||||
|
background-color: #282A32;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@ -539,11 +614,13 @@ export default defineComponent({
|
|||||||
font-size 14px;
|
font-size 14px;
|
||||||
padding-top 2px;
|
padding-top 2px;
|
||||||
overflow hidden
|
overflow hidden
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
max-width 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
//display none
|
display none
|
||||||
|
|
||||||
position absolute
|
position absolute
|
||||||
right 0;
|
right 0;
|
||||||
top 2px;
|
top 2px;
|
||||||
@ -558,8 +635,14 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
.btn-check {
|
||||||
|
.el-icon {
|
||||||
|
margin-left 10px;
|
||||||
|
font-size 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,6 +238,7 @@ export default defineComponent({
|
|||||||
connectingMessageBox: null, // 保存重连的消息框对象
|
connectingMessageBox: null, // 保存重连的消息框对象
|
||||||
errorMessage: null, // 错误信息提示框
|
errorMessage: null, // 错误信息提示框
|
||||||
socket: null,
|
socket: null,
|
||||||
|
activelyClose: false, // 主动关闭
|
||||||
mainWinHeight: 0, // 主窗口高度
|
mainWinHeight: 0, // 主窗口高度
|
||||||
chatBoxHeight: 0, // 聊天内容框高度
|
chatBoxHeight: 0, // 聊天内容框高度
|
||||||
leftBoxHeight: 0,
|
leftBoxHeight: 0,
|
||||||
@ -284,6 +285,12 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
// 创建 socket 会话连接
|
// 创建 socket 会话连接
|
||||||
connect: function () {
|
connect: function () {
|
||||||
|
// 先关闭已有连接
|
||||||
|
if (this.socket !== null) {
|
||||||
|
this.activelyClose = true;
|
||||||
|
this.socket.close();
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化 WebSocket 对象
|
// 初始化 WebSocket 对象
|
||||||
const sessionId = getSessionId();
|
const sessionId = getSessionId();
|
||||||
const socket = new WebSocket(process.env.VUE_APP_WS_HOST + `/api/chat?sessionId=${sessionId}&role=${this.role}`);
|
const socket = new WebSocket(process.env.VUE_APP_WS_HOST + `/api/chat?sessionId=${sessionId}&role=${this.role}`);
|
||||||
@ -303,6 +310,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.sending = false; // 允许用户发送消息
|
this.sending = false; // 允许用户发送消息
|
||||||
|
this.activelyClose = false;
|
||||||
if (this.errorMessage !== null) {
|
if (this.errorMessage !== null) {
|
||||||
this.errorMessage.close(); // 关闭错误提示信息
|
this.errorMessage.close(); // 关闭错误提示信息
|
||||||
}
|
}
|
||||||
@ -359,6 +367,10 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
|
|
||||||
socket.addEventListener('close', () => {
|
socket.addEventListener('close', () => {
|
||||||
|
if (this.activelyClose) { // 忽略主动关闭
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 停止送消息
|
// 停止送消息
|
||||||
this.sending = true;
|
this.sending = true;
|
||||||
this.checkSession();
|
this.checkSession();
|
||||||
|
Loading…
Reference in New Issue
Block a user