feat(聊天): 重构聊天功能,使用Vuex管理消息状态
- 将聊天消息和用户信息移至Vuex集中管理 - 实现打开或创建会话的统一入口方法openOrCreateDialogue - 更新消息列表获取和发送消息的逻辑 - 添加持久化存储支持保存聊天用户信息
This commit is contained in:
parent
9638bd10a1
commit
60dff46ffe
|
|
@ -2,7 +2,7 @@
|
||||||
<view class="chat-page">
|
<view class="chat-page">
|
||||||
<!-- 顶部导航 -->
|
<!-- 顶部导航 -->
|
||||||
<header-bar
|
<header-bar
|
||||||
:title="userName"
|
:title="vuex_msgUser.receiverName"
|
||||||
leftIcon="arrow-left"
|
leftIcon="arrow-left"
|
||||||
@leftClick="handleLeftClick"
|
@leftClick="handleLeftClick"
|
||||||
></header-bar>
|
></header-bar>
|
||||||
|
|
@ -16,12 +16,11 @@
|
||||||
scroll-with-animation
|
scroll-with-animation
|
||||||
>
|
>
|
||||||
<view
|
<view
|
||||||
v-for="(message, index) in messageList"
|
v-for="(message, index) in vuex_msgList"
|
||||||
:key="message.id"
|
:key="message.id"
|
||||||
:id="'msg-' + message.id"
|
:id="'msg-' + message.id"
|
||||||
>
|
>
|
||||||
<!-- 时间 -->
|
<!-- 时间 -->
|
||||||
<!-- v-if="message.timeLabel !== 0" -->
|
|
||||||
<view class="message-time" v-if="isShowTime(index)">
|
<view class="message-time" v-if="isShowTime(index)">
|
||||||
{{ formatShowTime(message.sendDate) }}
|
{{ formatShowTime(message.sendDate) }}
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -98,10 +97,6 @@ export default {
|
||||||
return {
|
return {
|
||||||
baseUrl: "",
|
baseUrl: "",
|
||||||
|
|
||||||
// 用户信息
|
|
||||||
userId: "",
|
|
||||||
userName: "",
|
|
||||||
|
|
||||||
// 头像
|
// 头像
|
||||||
myAvatar: "/static/avatar/default-avatar.png",
|
myAvatar: "/static/avatar/default-avatar.png",
|
||||||
otherAvatar: "/static/avatar/default-avatar.png",
|
otherAvatar: "/static/avatar/default-avatar.png",
|
||||||
|
|
@ -116,7 +111,6 @@ export default {
|
||||||
isRead: false,
|
isRead: false,
|
||||||
interactMode: 0,
|
interactMode: 0,
|
||||||
messageType: 0,
|
messageType: 0,
|
||||||
timeLabel: 1,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "02306fc3-c821-4a23-ad66-0bd77d154105",
|
id: "02306fc3-c821-4a23-ad66-0bd77d154105",
|
||||||
|
|
@ -127,8 +121,6 @@ export default {
|
||||||
isRead: false,
|
isRead: false,
|
||||||
interactMode: 1,
|
interactMode: 1,
|
||||||
messageType: 0,
|
messageType: 0,
|
||||||
timeLabel: 0,
|
|
||||||
displayTime: "",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "9cac8661-bf09-4b63-ab15-1a0a36b91110",
|
id: "9cac8661-bf09-4b63-ab15-1a0a36b91110",
|
||||||
|
|
@ -138,7 +130,6 @@ export default {
|
||||||
isRead: false,
|
isRead: false,
|
||||||
interactMode: 0,
|
interactMode: 0,
|
||||||
messageType: 0,
|
messageType: 0,
|
||||||
timeLabel: 1,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "02306fc3-c821-4a23-ad66-0bd788854105",
|
id: "02306fc3-c821-4a23-ad66-0bd788854105",
|
||||||
|
|
@ -148,8 +139,6 @@ export default {
|
||||||
isRead: false,
|
isRead: false,
|
||||||
interactMode: 1,
|
interactMode: 1,
|
||||||
messageType: 0,
|
messageType: 0,
|
||||||
timeLabel: 0,
|
|
||||||
displayTime: "",
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
@ -158,21 +147,19 @@ export default {
|
||||||
|
|
||||||
// 滚动位置
|
// 滚动位置
|
||||||
scrollToView: "",
|
scrollToView: "",
|
||||||
|
|
||||||
|
PageIndex: 1,
|
||||||
|
PageSize: 20,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
onLoad(options) {
|
onLoad(options) {
|
||||||
|
console.log(this.vuex_msgList);
|
||||||
|
|
||||||
this.baseUrl = this.$u.http.config.baseUrl;
|
this.baseUrl = this.$u.http.config.baseUrl;
|
||||||
|
|
||||||
// 获取传入的用户信息
|
|
||||||
this.userId = options.userId || "";
|
|
||||||
this.userName = options.name || "用户";
|
|
||||||
|
|
||||||
console.log("[聊天详情] 用户ID:", this.userId);
|
|
||||||
console.log("[聊天详情] 用户名:", this.userName);
|
|
||||||
|
|
||||||
// 加载历史消息
|
// 加载历史消息
|
||||||
this.loadHistoryMessages();
|
this.getMsgList();
|
||||||
|
|
||||||
// 滚动到底部
|
// 滚动到底部
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
|
|
@ -196,6 +183,18 @@ export default {
|
||||||
uni.navigateBack();
|
uni.navigateBack();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// this.vuex_msgUser = {
|
||||||
|
// dialogueManagementId: "08de36ed-8bc0-4b79-86e7-0128010ccc4b",
|
||||||
|
// receiverId: "08de33d5-b517-4801-8474-4a4ad5642691",
|
||||||
|
// receiverName: "华忠林",
|
||||||
|
// receiverHeadSculptureUrl: "tx.jpg",
|
||||||
|
// title: "",
|
||||||
|
// startTime: "2025-12-09T14:38:21.295504",
|
||||||
|
// lastMessageTime: "0001-01-01T00:00:00",
|
||||||
|
// isOverhead: false,
|
||||||
|
// unReadCount: 0,
|
||||||
|
// };
|
||||||
|
|
||||||
// 点击发送
|
// 点击发送
|
||||||
handleSend() {
|
handleSend() {
|
||||||
if (!this.messageValue) {
|
if (!this.messageValue) {
|
||||||
|
|
@ -204,10 +203,10 @@ export default {
|
||||||
|
|
||||||
// 构建消息对象
|
// 构建消息对象
|
||||||
const message = {
|
const message = {
|
||||||
dialogueManagementId: "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
dialogueManagementId: this.vuex_msgUser.dialogueManagementId,
|
||||||
receiverId: "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
receiverId: this.vuex_msgUser.receiverId,
|
||||||
messageType: 0,
|
|
||||||
message: this.messageValue,
|
message: this.messageValue,
|
||||||
|
messageType: 0,
|
||||||
filePath: "",
|
filePath: "",
|
||||||
ip: "",
|
ip: "",
|
||||||
};
|
};
|
||||||
|
|
@ -217,16 +216,30 @@ export default {
|
||||||
|
|
||||||
// 发送消息
|
// 发送消息
|
||||||
sendMsgFn(message) {
|
sendMsgFn(message) {
|
||||||
SendMessage_PrivateApi(message)
|
this.$u.api
|
||||||
|
.SendMessage_PrivateApi(message)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
console.log(res, "发送消息成功");
|
||||||
|
if (res.succeed) {
|
||||||
// 添加到消息列表
|
// 添加到消息列表
|
||||||
this.messageList.push(message);
|
const msgUserData = {
|
||||||
|
dialogueManagementId: this.vuex_msgUser.dialogueManagementId,
|
||||||
|
senderId: this.vuex_user.Id,
|
||||||
|
receiverId: this.vuex_msgUser.receiverId,
|
||||||
|
sendDate: new Date().toISOString(),
|
||||||
|
message: this.messageValue,
|
||||||
|
messageType: 0,
|
||||||
|
filePath: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$store.commit("push_Msg", msgUserData);
|
||||||
// 清空输入框
|
// 清空输入框
|
||||||
this.messageValue = "";
|
this.messageValue = "";
|
||||||
// 滚动到底部
|
// 滚动到底部
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.scrollToBottom();
|
this.scrollToBottom();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
return msg.warning("发送失败");
|
return msg.warning("发送失败");
|
||||||
|
|
@ -249,22 +262,35 @@ export default {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// 加载历史消息
|
// 加载对话消息
|
||||||
loadHistoryMessages() {
|
getMsgList() {
|
||||||
// TODO: 从服务器加载历史消息
|
this.$u.api
|
||||||
// this.$u.api.getChatHistory({
|
.GetChatHistoryDataApi({
|
||||||
// userId: this.userId
|
"Item1.DialogueManagementId": this.vuex_msgUser.dialogueManagementId,
|
||||||
// }).then(res => {
|
PageIndex: this.PageIndex,
|
||||||
// this.messageList = res.data
|
PageSize: this.PageSize,
|
||||||
// })
|
})
|
||||||
|
.then((res) => {
|
||||||
|
const msgList = res.data.item1.reverse();
|
||||||
|
// 注:现在的消息返回值缺少 interactMode 字段,先手动mock
|
||||||
|
|
||||||
console.log("[聊天详情] 加载历史消息");
|
for (var i = 0; i < msgList.length; i++) {
|
||||||
|
msgList[i].interactMode = msgList[i].interactMode || 0;
|
||||||
|
|
||||||
|
// if (this.PageIndex != 1) {
|
||||||
|
// this.$store.commit("unshift_Msg", msgList[i]);
|
||||||
|
// } else {
|
||||||
|
// this.$store.commit("push_Msg", msgList[i]);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
this.$store.commit("push_MsgList", msgList);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// 滚动到底部
|
// 滚动到底部
|
||||||
scrollToBottom() {
|
scrollToBottom() {
|
||||||
if (this.messageList.length > 0) {
|
if (this.vuex_msgList.length > 0) {
|
||||||
const lastMsg = this.messageList[this.messageList.length - 1];
|
const lastMsg = this.vuex_msgList[this.vuex_msgList.length - 1];
|
||||||
this.scrollToView = "msg-" + lastMsg.id;
|
this.scrollToView = "msg-" + lastMsg.id;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -281,8 +307,8 @@ export default {
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
let isTime = new Date(this.messageList[index].sendDate).getTime(); //当前时间
|
let isTime = new Date(this.vuex_msgList[index].sendDate).getTime(); //当前时间
|
||||||
const time = new Date(this.messageList[index - 1].sendDate).getTime(); //上条消息的时间
|
const time = new Date(this.vuex_msgList[index - 1].sendDate).getTime(); //上条消息的时间
|
||||||
// 30 分钟内不显示时间提示
|
// 30 分钟内不显示时间提示
|
||||||
return isTime - time > 30 * 60 * 1000;
|
return isTime - time > 30 * 60 * 1000;
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -104,10 +104,18 @@ export default {
|
||||||
uni.navigateBack();
|
uni.navigateBack();
|
||||||
},
|
},
|
||||||
handleAskQuestion(teacher) {
|
handleAskQuestion(teacher) {
|
||||||
// 跳转老师详情
|
console.log("点击咨询:", teacher);
|
||||||
uni.navigateTo({
|
|
||||||
url: `/pages/home/teacherInfo/index?teacherId=${teacher.id}`,
|
var msgUserData = {
|
||||||
});
|
avatar: teacher.headSculptureUrl,
|
||||||
|
friendId: teacher.id,
|
||||||
|
friendName: teacher.name,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 进入对话会话
|
||||||
|
this.$store.dispatch("openOrCreateDialogue", msgUserData);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
// 留言相关的没用了,先注释
|
// 留言相关的没用了,先注释
|
||||||
|
|
@ -118,6 +126,7 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 提交留言(此方法废弃)
|
// 提交留言(此方法废弃)
|
||||||
handleMessageSubmit(data) {
|
handleMessageSubmit(data) {
|
||||||
console.log("提交留言:", data.content, "教师:", data.teacher?.name);
|
console.log("提交留言:", data.content, "教师:", data.teacher?.name);
|
||||||
|
|
|
||||||
133
store/index.js
133
store/index.js
|
|
@ -11,7 +11,12 @@ try {
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|
||||||
// 需要永久存储,且下次APP启动需要取出的,在state中的变量名
|
// 需要永久存储,且下次APP启动需要取出的,在state中的变量名
|
||||||
let saveStateKeys = ["vuex_user", "vuex_token", "vuex_userType"];
|
let saveStateKeys = [
|
||||||
|
"vuex_user",
|
||||||
|
"vuex_token",
|
||||||
|
"vuex_userType",
|
||||||
|
"vuex_msgUser",
|
||||||
|
];
|
||||||
|
|
||||||
// 保存变量到本地存储中
|
// 保存变量到本地存储中
|
||||||
const saveLifeData = function (key, value) {
|
const saveLifeData = function (key, value) {
|
||||||
|
|
@ -45,7 +50,7 @@ const store = new Vuex.Store({
|
||||||
// 本地占位的聊天用户(未在服务端建立的会话,临时展示)
|
// 本地占位的聊天用户(未在服务端建立的会话,临时展示)
|
||||||
vuex_localMsgUserList: [],
|
vuex_localMsgUserList: [],
|
||||||
// 当前聊天用户对象
|
// 当前聊天用户对象
|
||||||
vuex_msgUser: null,
|
vuex_msgUser: lifeData.vuex_msgUser ? lifeData.vuex_msgUser : {},
|
||||||
// 消息窗口滚动位置
|
// 消息窗口滚动位置
|
||||||
vuex_msgScrollTop: 0,
|
vuex_msgScrollTop: 0,
|
||||||
// 自定义tabbar数据
|
// 自定义tabbar数据
|
||||||
|
|
@ -118,7 +123,7 @@ const store = new Vuex.Store({
|
||||||
|
|
||||||
// ===== 消息中心:列表、当前聊天、消息推送等 =====
|
// ===== 消息中心:列表、当前聊天、消息推送等 =====
|
||||||
// 设置会话列表(服务端返回)
|
// 设置会话列表(服务端返回)
|
||||||
setUserMsgList(state, list) {
|
set_UserMsgList(state, list) {
|
||||||
state.vuex_userMsgList = Array.isArray(list) ? list.slice() : [];
|
state.vuex_userMsgList = Array.isArray(list) ? list.slice() : [];
|
||||||
if (state.vuex_msgUser && state.vuex_msgUser.friendId) {
|
if (state.vuex_msgUser && state.vuex_msgUser.friendId) {
|
||||||
state.vuex_userMsgList = state.vuex_userMsgList.map((item) => {
|
state.vuex_userMsgList = state.vuex_userMsgList.map((item) => {
|
||||||
|
|
@ -130,7 +135,7 @@ const store = new Vuex.Store({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 插入一个本地占位的聊天用户
|
// 插入一个本地占位的聊天用户
|
||||||
addLocalMsgUser(state, user) {
|
add_LocalMsgUser(state, user) {
|
||||||
const existsLocal = (state.vuex_localMsgUserList || []).some(
|
const existsLocal = (state.vuex_localMsgUserList || []).some(
|
||||||
(v) => v && v.friendId === user.friendId
|
(v) => v && v.friendId === user.friendId
|
||||||
);
|
);
|
||||||
|
|
@ -156,7 +161,7 @@ const store = new Vuex.Store({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 设置当前聊天用户
|
// 设置当前聊天用户
|
||||||
setMsgUser(state, user) {
|
set_MsgUser(state, user) {
|
||||||
state.vuex_msgUser = user || null;
|
state.vuex_msgUser = user || null;
|
||||||
if (state.vuex_msgUser && state.vuex_msgUser.friendId) {
|
if (state.vuex_msgUser && state.vuex_msgUser.friendId) {
|
||||||
state.vuex_userMsgList = (state.vuex_userMsgList || []).map((item) => {
|
state.vuex_userMsgList = (state.vuex_userMsgList || []).map((item) => {
|
||||||
|
|
@ -167,23 +172,28 @@ const store = new Vuex.Store({
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// 现在没有id,先覆盖整个list
|
||||||
|
push_MsgList(state, list) {
|
||||||
|
state.vuex_msgList = list || [];
|
||||||
|
},
|
||||||
// 推送一条新消息(去重)
|
// 推送一条新消息(去重)
|
||||||
pushMsg(state, msg) {
|
push_Msg(state, msg) {
|
||||||
if (!msg || !msg.id) return;
|
// 注:现在的消息没有id,暂时注释
|
||||||
const exists = (state.vuex_msgList || []).some(
|
// if (!msg || !msg.id) return;
|
||||||
(item) => item && item.id === msg.id
|
// const exists = (state.vuex_msgList || []).some(
|
||||||
);
|
// (item) => item && item.id === msg.id
|
||||||
if (!exists) {
|
// );
|
||||||
|
// if (!exists) {
|
||||||
state.vuex_msgList.push(msg);
|
state.vuex_msgList.push(msg);
|
||||||
}
|
// }
|
||||||
},
|
},
|
||||||
// 插入历史消息到头部
|
// 插入历史消息到头部
|
||||||
unshiftMsg(state, msg) {
|
unshift_Msg(state, msg) {
|
||||||
if (!msg) return;
|
if (!msg) return;
|
||||||
state.vuex_msgList.unshift(msg);
|
state.vuex_msgList.unshift(msg);
|
||||||
},
|
},
|
||||||
// 更新置顶状态(本地)
|
// 更新置顶状态(本地)
|
||||||
updateTopState(state, { friendId, isTop }) {
|
update_TopState(state, { friendId, isTop }) {
|
||||||
state.vuex_userMsgList = (state.vuex_userMsgList || []).map((item) => {
|
state.vuex_userMsgList = (state.vuex_userMsgList || []).map((item) => {
|
||||||
if (item && item.friendId === friendId) {
|
if (item && item.friendId === friendId) {
|
||||||
return { ...item, isTop: !!isTop };
|
return { ...item, isTop: !!isTop };
|
||||||
|
|
@ -192,11 +202,11 @@ const store = new Vuex.Store({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 更新消息窗口滚动位置
|
// 更新消息窗口滚动位置
|
||||||
setMsgScrollTop(state, top) {
|
set_MsgScrollTop(state, top) {
|
||||||
state.vuex_msgScrollTop = Number(top) || 0;
|
state.vuex_msgScrollTop = Number(top) || 0;
|
||||||
},
|
},
|
||||||
// 清空消息相关状态(登出/切换账号)
|
// 清空消息相关状态(登出/切换账号)
|
||||||
clearMessageState(state) {
|
clear_MessageState(state) {
|
||||||
state.vuex_msgList = [];
|
state.vuex_msgList = [];
|
||||||
state.vuex_userMsgList = [];
|
state.vuex_userMsgList = [];
|
||||||
state.vuex_localMsgUserList = [];
|
state.vuex_localMsgUserList = [];
|
||||||
|
|
@ -220,36 +230,39 @@ const store = new Vuex.Store({
|
||||||
saveLifeData("vuex_token", state.vuex_token);
|
saveLifeData("vuex_token", state.vuex_token);
|
||||||
saveLifeData("vuex_teacherInfo", state.vuex_teacherInfo);
|
saveLifeData("vuex_teacherInfo", state.vuex_teacherInfo);
|
||||||
saveLifeData("vuex_user", state.vuex_user);
|
saveLifeData("vuex_user", state.vuex_user);
|
||||||
|
saveLifeData("vuex_msgUser", state.vuex_msgUser);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
// 获取聊天列表(最近联系人)
|
// 获取聊天列表(最近联系人)
|
||||||
async getUserlist({ commit, state }) {
|
async getUserlist({ commit, state }) {
|
||||||
this.$u.api.GetDialogueListApi().then((res) => {
|
// 在 Vuex action 中没有组件 this,上下文不包含 $u
|
||||||
const baseUrl =
|
// 通过 Vue.prototype.$u 使用 uView 的 http 实例
|
||||||
(Vue.prototype.$u &&
|
return Vue.prototype.$u.api.GetDialogueListApi().then((res) => {
|
||||||
Vue.prototype.$u.http &&
|
const list = (res && res.data.item1 ? res.data.item1 : []).map(
|
||||||
Vue.prototype.$u.http.config &&
|
(item) => {
|
||||||
Vue.prototype.$u.http.config.baseUrl) ||
|
|
||||||
"";
|
|
||||||
const list = (res && res.data ? res.data : []).map((item) => {
|
|
||||||
const unReadCount =
|
const unReadCount =
|
||||||
state.vuex_msgUser && state.vuex_msgUser.friendId === item.friendId
|
state.vuex_msgUser &&
|
||||||
|
state.vuex_msgUser.friendId === item.friendId
|
||||||
? 0
|
? 0
|
||||||
: item.unReadCount || 0;
|
: item.unReadCount || 0;
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
avatar: baseUrl ? baseUrl + item.avatar : item.avatar,
|
// avatar: item.avatar,
|
||||||
unReadCount,
|
unReadCount,
|
||||||
};
|
};
|
||||||
});
|
}
|
||||||
commit("setUserMsgList", list);
|
);
|
||||||
|
commit("set_UserMsgList", list);
|
||||||
|
return list;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 设置当前聊天用户并入队本地占位
|
// 设置当前聊天用户并入队本地占位
|
||||||
setMsgUser({ commit, dispatch }, user) {
|
setMsgUser({ commit, dispatch }, user) {
|
||||||
commit("setMsgUser", user);
|
console.log("setMsgUser执行了", user);
|
||||||
commit("addLocalMsgUser", user);
|
|
||||||
|
commit("set_MsgUser", user);
|
||||||
|
commit("add_LocalMsgUser", user);
|
||||||
// 刷新列表,清零未读
|
// 刷新列表,清零未读
|
||||||
dispatch("getUserlist");
|
dispatch("getUserlist");
|
||||||
},
|
},
|
||||||
|
|
@ -260,10 +273,10 @@ const store = new Vuex.Store({
|
||||||
) {
|
) {
|
||||||
const params = { userId, friendId, PageIndex, PageSize };
|
const params = { userId, friendId, PageIndex, PageSize };
|
||||||
|
|
||||||
this.$u.api.GetChatHistoryDataApi(params).then((res) => {
|
Vue.prototype.$u.api.GetChatHistoryDataApi(params).then((res) => {
|
||||||
const list = res && res.data ? res.data : [];
|
const list = res && res.data ? res.data : [];
|
||||||
// 将最新消息插入到消息列表尾部(或头部)
|
// 将最新消息插入到消息列表尾部(或头部)
|
||||||
list.forEach((msg) => commit("pushMsg", msg));
|
list.forEach((msg) => commit("push_Msg", msg));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 设置消息置顶(服务端 + 本地)
|
// 设置消息置顶(服务端 + 本地)
|
||||||
|
|
@ -272,14 +285,66 @@ const store = new Vuex.Store({
|
||||||
if (user.isTop) {
|
if (user.isTop) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
this.$u.api
|
Vue.prototype.$u.api
|
||||||
.OverheadOneDialogueApi({ dialogueManagementId: user.friendId })
|
.OverheadOneDialogueApi({ dialogueManagementId: user.friendId })
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
commit("updateTopState", { friendId: user.friendId, isTop: true });
|
commit("update_TopState", { friendId: user.friendId, isTop: true });
|
||||||
dispatch("getUserlist");
|
dispatch("getUserlist");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 统一入口:打开或创建会话
|
||||||
|
// 使用位置:所有需要进入聊天的入口调用该方法,避免各页面重复逻辑
|
||||||
|
// 1) 获取最新会话列表
|
||||||
|
// 2) 查找是否存在 friendId 对应的会话
|
||||||
|
// 3) 有则设置当前会话并(可选)跳转;无则创建,成功后递归重试
|
||||||
|
async openOrCreateDialogue({ commit, state, dispatch }, user) {
|
||||||
|
const { friendId, friendName, avatar, chatType = 0 } = user || {};
|
||||||
|
const attempt =
|
||||||
|
user && typeof user.attempt === "number" ? user.attempt : 1;
|
||||||
|
if (!friendId) return Promise.reject(new Error("缺少 friendId"));
|
||||||
|
|
||||||
|
// 第一步:获取列表(复用现有 action,保证 state 同步更新)
|
||||||
|
const list = await dispatch("getUserlist");
|
||||||
|
|
||||||
|
// 第二步:查找是否存在该会话(兼容后端字段 friendId/receiverId)
|
||||||
|
const target = (list || []).find(
|
||||||
|
(i) => i && (i.receiverId === friendId || i.friendId === friendId)
|
||||||
|
);
|
||||||
|
if (target) {
|
||||||
|
commit("set_MsgUser", target);
|
||||||
|
|
||||||
|
// 跳转到对话页,参数按需调整
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/chat/index`,
|
||||||
|
});
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 第二次调用时,无论成功与否均在第三步(创建)之前结束
|
||||||
|
if (attempt >= 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 第三步:不存在则创建,成功后重试本流程
|
||||||
|
const res = await Vue.prototype.$u.api.AddDialogueApi({
|
||||||
|
receiverId: friendId,
|
||||||
|
onlineConsultationType: 0, // 0:招生在线;1:迎新在线(可按业务传入)
|
||||||
|
});
|
||||||
|
if (res && res.succeed === true) {
|
||||||
|
// 创建成功后,重新执行流程(再次获取列表并进入会话)
|
||||||
|
return dispatch("openOrCreateDialogue", {
|
||||||
|
friendId,
|
||||||
|
friendName,
|
||||||
|
avatar,
|
||||||
|
chatType,
|
||||||
|
attempt: attempt + 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res?.error || "创建会话失败"));
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue