介绍
侧边栏对会话组进行了管理,保存用户的历史会话,方便查看,便于双屏对照内容,提高工作效率。其具有显示历史会话、新建会话、删除会话和修改会话标题等功能。
显示会话
从本地存储(localStorage)中加载聊天对话列表,确保即使没有保存的对话或者保存的数据损坏,应用也能正确地初始化对话列表,并能够在有有效数据时加载这些数据。
loadConversationFromLocal() {
// 尝试从localStorage获取保存的对话列表
const savedConversations = localStorage.getItem('conversations');
// 检查是否有数据,如果有,解析JSON格式的字符串转换回数组
if (savedConversations) {
try {
// 将JSON字符串转换成JavaScript对象
this.setConversationList(JSON.parse(savedConversations));
} catch (e) {
// 如果解析出错,可能是数据损坏或格式不正确
console.error('Failed to parse conversations from localStorage:', e);
// 可以选择清空损坏的数据或给出错误提示
this.conversations = [];
}
} else {
// 如果本地存储中没有对话列表,初始化为空数组
this.conversations = [];
}
}
新建会话
创建一个新的会话对象,将该对象添加到会话列表的前面,保存所有会话到本地存储,并选择最新的会话作为活动状态。
当用户在输入框中点击发送按钮且没有现有会话时,将通过总线机制在兄弟组件间传递消息以创建新的会话。具体来说,总线系统会监听bus-send
事件,一旦该事件被触发,busSend
方法就会被调用。这个方法会检查Vuex中的会话ID,并在会话列表中寻找对应的会话。如果没有找到,则会创建一个新的会话对象,并将其消息列表设置为当前的messageList
,确保用户刚输入的消息成为新会话的一部分。
newChat(msgList) {
this.chatTitle = "New chat";
document.title = "New chat";
let newConv = {
"id": Date.now(),
"title": "New chat",
"msgList": msgList,
}
//add the conv to the list
this.unshiftConversationList(newConv);
//save the conv list to local storage
this.saveConversations();
this.selectConversation(this.conversations.length - 1);
}
unshiftConversationList
方法将新创建的会话对象newConv
添加到现有会话列表的前面。unshift
是JavaScript数组的一个方法,它会在数组的开头添加一个或多个元素,并返回新的长度。
saveConversations
方法调用保存所有会话到本地存储,以便即使页面刷新或重新加载,会话也能持久化保存。
saveConversations() {
var conversations = JSON.parse(JSON.stringify(this.getConversationList));
for (let idx in conversations) {
var conv = conversations[idx];
delete conv.editable;
delete conv.selected;
delete conv.delete;
}
let convs = JSON.stringify(conversations);
localStorage.setItem("conversations", convs);
}
selectConversation
方法选择最新的会话,即刚创建的会话,使它成为活动状态,用户可以看到并与之交互。
selectConversation(cidx) {
if (cidx < 0 || cidx >= this.getConversationList.length) {
console.log("invalid index")
return;
}
//get the conversation which you want to select by index
var conv = this.getConversationByIndex(cidx);
//if the conversation is already selected, return
if (this.oldConv && this.oldConv.id == conv.id) {
console.log("same conversation")
return;
}
//set the old conversation to unselected
if (this.oldConv) {
this.oldConv.selected = false;
}
//set the new conversation to selected
conv.selected = true
this.setSelectedIdx(cidx);
this.oldConv = conv;
document.title = conv.title || "chatai";
this.chatTitle = conv.title || "chatai";
//set the conversation to vuex
this.setConversation(conv);
this.conversations[cidx] = conv;
}
删除会话
state
是一个包含聊天会话列表的状态对象,index
是要从列表中删除的会话的索引,删除指定索引的聊天会话。在不可变数据结构的应用中,通常会返回一个新的状态对象而不是修改原始对象。
delConversationByIndex(state:stateType, index:number) {
if (state.conversationList != null&&state.conversationList.length>index)
state.conversationList.splice(index, 1);
else console.log("delConversationByIndex fail",state.conversationList,index);
}
清空所有历史会话
clearConversations() {
this.conversations = []
this.saveConversations();
}
会话选择
选择一个特定的聊天对话,并更新页面状态以反映这一选择。在用户选择不同的对话时,更新当前状态,包括选中的对话、浏览器标签页的标题和可能的状态管理库中的状态。
selectConversation(cidx) {
if (cidx < 0 || cidx >= this.getConversationList.length) {
console.log("invalid index")
return;
}
//get the conversation which you want to select by index
var conv = this.getConversationByIndex(cidx);
//if the conversation is already selected, return
if (this.oldConv && this.oldConv.id == conv.id) {
console.log("same conversation")
return;
}
//set the old conversation to unselected
if (this.oldConv) {
this.oldConv.selected = false;
}
//set the new conversation to selected
conv.selected = true
this.setSelectedIdx(cidx);
this.oldConv = conv;
document.title = conv.title || "chatai";
this.chatTitle = conv.title || "chatai";
//set the conversation to vuex
this.setConversation(conv);
this.conversations[cidx] = conv;
}
修改会话
用户可编辑指定索引的聊天对话标题,提供了一个用户友好的方式来编辑聊天对话的标题,通过设置对话的可编辑状态,并提供自动聚焦输入框的功能。
下述方法会将对应会话的editable
属性设置为true
,表明会话标题现在处于可编辑状态。同时,方法还会将会话当前的title
存储在convTitletmp
变量中,以便在需要时恢复原始标题。一旦editable
属性被设置为true
,这将触发v-if
指令,进而改变DOM的渲染。原本显示标题的文本将转换成一个输入框,其初始内容为convTitletmp
变量的值。这样用户就可以直接在输入框中编辑标题,而无需手动点击输入框。
editTitle(cidx) {
if (cidx < 0 || cidx >= this.conversations.length) {
alert("invalid index")
console.log("invalid index")
return;
}
var conv = this.conversations[cidx];
this.convTitletmp = conv.title;
conv.editable = true;
this.conversations[cidx] = conv;
setTimeout(() => {
document.getElementById("titleInput").focus();
}, 150)
}
取消修改
在用户取消编辑对话标题时,将对话的editable
属性设置为false
,并更新对话列表(如果取消注释的话),以确保用户界面正确地反映出对话标题的编辑状态。
cancelChangeConvTitle(idx, conv) {
conv.editable = false;
//this.conversations[idx] = conv;
}
确认修改
修改会话对象的标题,调用方法修改vuex中全局的conversationList对象,调用saveConversations方法,把conversations保存到loacalStorage中。
changeConvTitle(idx, conv) {
conv.title = this.convTitletmp;
this.setConversationByIndex({ cidx: idx, conv: conv });
this.saveConversations();
this.cancelChangeConvTitle(idx, conv)
}