Compare commits
No commits in common. "76fc04f7585fdea35bf03b88a6985a8ff41645c3" and "0783e4a0577ced246a15bbfa1eaaffdeafcea353" have entirely different histories.
76fc04f758
...
0783e4a057
70
App.vue
70
App.vue
|
|
@ -200,11 +200,11 @@ export default {
|
|||
if (type === "pong") return;
|
||||
|
||||
// 退出登录通知
|
||||
if (type === "Exit") {
|
||||
try {
|
||||
this.ws && this.ws.close();
|
||||
} catch (err) {}
|
||||
// 清理本地登录信息并返回登录页
|
||||
if (type === "Exit") {
|
||||
try {
|
||||
this.ws && this.ws.close();
|
||||
} catch (err) {}
|
||||
// 清理本地登录信息并返回登录页
|
||||
this.$u.vuex("vuex_user", "");
|
||||
this.$u.vuex("vuex_token", "");
|
||||
uni.clearStorage();
|
||||
|
|
@ -220,45 +220,35 @@ export default {
|
|||
this.$u.vuex("vuex_tabbar", tab);
|
||||
}
|
||||
|
||||
// 收到私聊消息
|
||||
if (type === "PrivateChatMessage") {
|
||||
const data = msgData.Data || {};
|
||||
const dialogueManagementId = data.DialogueManagementId || "";
|
||||
const processData = {
|
||||
dialogueManagementId,
|
||||
senderId: data.SenderId,
|
||||
// 收到私聊消息
|
||||
if (type === "PrivateChatMessage") {
|
||||
const data = msgData.Data || {};
|
||||
const processData = {
|
||||
dialogueManagementId: data.DialogueManagementId,
|
||||
senderId: data.SenderId,
|
||||
receiverId: data.ReceiverId,
|
||||
sendDate: data.SendDate,
|
||||
message: data.Message,
|
||||
};
|
||||
const id = data.Id || data.id || Math.random().toString(36).substring(2);
|
||||
const msg = {
|
||||
...processData,
|
||||
messageType: 0,
|
||||
filePath: "",
|
||||
id,
|
||||
};
|
||||
const storeState = (this.$store && this.$store.state) || {};
|
||||
const isTransferChat = !!storeState.vuex_isTransferChat;
|
||||
|
||||
if (isTransferChat) {
|
||||
this.$store.commit("push_AiLiveAgentMsg", msg);
|
||||
} else {
|
||||
this.$store.commit("push_Msg", msg);
|
||||
}
|
||||
|
||||
// 更新会话列表的未读数 / 文案 / 时间,保持实时展示
|
||||
if (processData.dialogueManagementId) {
|
||||
this.$store.commit("apply_RealtimeMessageToList", {
|
||||
dialogueId: processData.dialogueManagementId,
|
||||
message: processData.message,
|
||||
sendDate: processData.sendDate,
|
||||
senderId: processData.senderId,
|
||||
receiverId: processData.receiverId,
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
this.$store.commit("push_Msg", {
|
||||
...processData,
|
||||
messageType: 0,
|
||||
filePath: "",
|
||||
id: Math.random().toString(36).substring(2),
|
||||
});
|
||||
|
||||
// 更新会话列表的未读数 / 文案 / 时间,保持实时展示
|
||||
if (processData.dialogueManagementId) {
|
||||
this.$store.commit("apply_RealtimeMessageToList", {
|
||||
dialogueId: processData.dialogueManagementId,
|
||||
message: processData.message,
|
||||
sendDate: processData.sendDate,
|
||||
senderId: processData.senderId,
|
||||
receiverId: processData.receiverId,
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
// 连接关闭
|
||||
handleWsClose(e) {
|
||||
// console.log(`[WebSocket] 连接关闭: code=${e.code}, reason=${e.reason}`);
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@
|
|||
<view class="feature-grid">
|
||||
<view
|
||||
class="feature-item"
|
||||
v-for="(item, index) in displayFeatures"
|
||||
v-for="(item, index) in features"
|
||||
:key="index"
|
||||
:style="{
|
||||
background: item.background,
|
||||
|
|
@ -282,33 +282,6 @@
|
|||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 转人工消息 -->
|
||||
<!-- 8 人工回复 -->
|
||||
<view
|
||||
class="message-left"
|
||||
v-else-if="message.interactMode === 8"
|
||||
:id="'msg-' + message.id"
|
||||
>
|
||||
<image
|
||||
class="ai-avatar"
|
||||
:src="receiverHeadSculptureUrl"
|
||||
mode="scaleToFill"
|
||||
/>
|
||||
<view
|
||||
class="message-content"
|
||||
:class="{
|
||||
'message-content-width': !message.isLoading,
|
||||
}"
|
||||
>
|
||||
<view v-if="message.isLoading" class="loading-dots">
|
||||
<view class="dot"></view>
|
||||
<view class="dot"></view>
|
||||
<view class="dot"></view>
|
||||
</view>
|
||||
<markdown-viewer v-else :content="message.message" />
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
|
@ -512,50 +485,14 @@ export default {
|
|||
|
||||
return "/static/common/images/avatar.png";
|
||||
},
|
||||
receiverHeadSculptureUrl() {
|
||||
const url =
|
||||
(this.vuex_msgUser &&
|
||||
(this.vuex_msgUser.headSculptureUrl ||
|
||||
this.vuex_msgUser.HeadSculptureUrl)) ||
|
||||
"";
|
||||
if (url) {
|
||||
return this.baseUrl + "/" + url;
|
||||
}
|
||||
|
||||
return "/static/common/images/avatar_default2.png";
|
||||
},
|
||||
aiMessageGroups() {
|
||||
return Array.isArray(this.vuex_aiMessageGroups)
|
||||
? this.vuex_aiMessageGroups
|
||||
: [];
|
||||
},
|
||||
displayFeatures() {
|
||||
const list = Array.isArray(this.features) ? this.features : [];
|
||||
return list.map((item) => {
|
||||
if (item && item.title === "转人工") {
|
||||
return {
|
||||
...item,
|
||||
title: this.vuex_isTransferChat ? "结束会话" : "转人工",
|
||||
};
|
||||
}
|
||||
return item;
|
||||
});
|
||||
},
|
||||
isLiveAgentChat() {
|
||||
if (!this.vuex_isTransferChat) return false;
|
||||
const current = this.currentDMid || "";
|
||||
const active = this.vuex_msgUser && this.vuex_msgUser.dialogueManagementId;
|
||||
return !!(current && active && String(active) === String(current));
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
currentDMid: {
|
||||
handler(val) {
|
||||
this.$store.commit("set_AiActiveDMid", val || "");
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
// 确保消息更新后自动滚动到底部
|
||||
aiMessageGroups: {
|
||||
handler() {
|
||||
|
|
@ -682,10 +619,6 @@ export default {
|
|||
this.handleTransferEntryClick();
|
||||
return;
|
||||
}
|
||||
if (item.title === "结束会话") {
|
||||
this.$store.commit("set_IsTransferChat", false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.title === "电话咨询") {
|
||||
this.advicePhoneShow = true;
|
||||
|
|
@ -776,17 +709,6 @@ export default {
|
|||
(m) => m && m.customType === "transferCard"
|
||||
);
|
||||
};
|
||||
const updateTransferCard = (patch) => {
|
||||
const list = this.aiMessageGroups;
|
||||
const idx = findCardIndex(list);
|
||||
if (idx < 0) return false;
|
||||
const current = list[idx] || {};
|
||||
const next = { ...current, ...patch };
|
||||
const nextList = list.slice();
|
||||
nextList.splice(idx, 1, next);
|
||||
this.$store.commit("push_AiMsgList", nextList);
|
||||
return true;
|
||||
};
|
||||
const list = this.aiMessageGroups;
|
||||
const idx = findCardIndex(list);
|
||||
if (idx < 0) return;
|
||||
|
|
@ -794,11 +716,15 @@ export default {
|
|||
const current = list[idx] || {};
|
||||
if (this.isTransferSubmitting || current.transferStatus === "done") return;
|
||||
|
||||
updateTransferCard({
|
||||
const next = {
|
||||
...current,
|
||||
transferStatus: "idle",
|
||||
selectedConsultationType: consultationType,
|
||||
transferTipText: "",
|
||||
});
|
||||
};
|
||||
const nextList = list.slice();
|
||||
nextList.splice(idx, 1, next);
|
||||
this.$store.commit("push_AiMsgList", nextList);
|
||||
this.isTransferSubmitting = true;
|
||||
|
||||
const params = {
|
||||
|
|
@ -814,59 +740,48 @@ export default {
|
|||
this.$u.api
|
||||
.TransferToALiveAgentApi(params)
|
||||
.then((res) => {
|
||||
this.isTransferSubmitting = false;
|
||||
const latestList = this.aiMessageGroups;
|
||||
const nextIdx = findCardIndex(latestList);
|
||||
if (nextIdx < 0) return;
|
||||
const succeed = res && res.succeed !== false;
|
||||
const serverTip = (res && res.data && res.data.message) || (res && res.error) || "";
|
||||
const serverTip =
|
||||
(res && res.data && res.data.message) ||
|
||||
(res && res.error) ||
|
||||
"";
|
||||
if (!succeed) {
|
||||
updateTransferCard({
|
||||
const updated = {
|
||||
...latestList[nextIdx],
|
||||
transferStatus: "idle",
|
||||
transferTipText: serverTip,
|
||||
});
|
||||
};
|
||||
const updatedList = latestList.slice();
|
||||
updatedList.splice(nextIdx, 1, updated);
|
||||
this.$store.commit("push_AiMsgList", updatedList);
|
||||
return;
|
||||
}
|
||||
|
||||
const dialogueManagementId =
|
||||
this.currentDMid ||
|
||||
(res &&
|
||||
res.data &&
|
||||
(res.data.dialogueManagementId ||
|
||||
res.data.DialogueManagementId)) ||
|
||||
"";
|
||||
const receiverId =
|
||||
(res &&
|
||||
res.data &&
|
||||
(res.data.receiverId ||
|
||||
res.data.ReceiverId ||
|
||||
res.data.liveAgentId ||
|
||||
res.data.agentId ||
|
||||
res.data.userId)) ||
|
||||
"";
|
||||
|
||||
if (!this.currentDMid && dialogueManagementId) {
|
||||
this.currentDMid = dialogueManagementId;
|
||||
}
|
||||
|
||||
updateTransferCard({
|
||||
const updated = {
|
||||
...latestList[nextIdx],
|
||||
transferStatus: "done",
|
||||
transferTipText: serverTip,
|
||||
});
|
||||
|
||||
if (dialogueManagementId && receiverId) {
|
||||
this.$store.commit("set_IsTransferChat", true);
|
||||
this.$store.dispatch("selectTeacherChatItem", {
|
||||
id: dialogueManagementId,
|
||||
receiverId,
|
||||
navigate: false,
|
||||
});
|
||||
}
|
||||
};
|
||||
const updatedList = latestList.slice();
|
||||
updatedList.splice(nextIdx, 1, updated);
|
||||
this.$store.commit("push_AiMsgList", updatedList);
|
||||
})
|
||||
.catch(() => {
|
||||
updateTransferCard({
|
||||
this.isTransferSubmitting = false;
|
||||
const latestList = this.aiMessageGroups;
|
||||
const nextIdx = findCardIndex(latestList);
|
||||
if (nextIdx < 0) return;
|
||||
const updated = {
|
||||
...latestList[nextIdx],
|
||||
transferStatus: "idle",
|
||||
transferTipText: "转人工失败,请稍后重试",
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
this.isTransferSubmitting = false;
|
||||
};
|
||||
const updatedList = latestList.slice();
|
||||
updatedList.splice(nextIdx, 1, updated);
|
||||
this.$store.commit("push_AiMsgList", updatedList);
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -899,11 +814,6 @@ export default {
|
|||
this.$store.commit("push_AiMsg", userMessage);
|
||||
this.messageValue = "";
|
||||
|
||||
if (this.isLiveAgentChat) {
|
||||
this.sendLiveAgentTextMessage(sendMessage, userMessage.id);
|
||||
return;
|
||||
}
|
||||
|
||||
// 立即添加一个AI回复的加载状态消息
|
||||
const loadingMessage = {
|
||||
id: "loading_" + Math.random().toString(36).substring(2, 15),
|
||||
|
|
@ -1019,11 +929,6 @@ export default {
|
|||
// 添加到消息列表
|
||||
this.$store.commit("push_AiMsg", userMessage);
|
||||
|
||||
if (this.isLiveAgentChat) {
|
||||
this.sendLiveAgentTextMessage(sendMessage, userMessage.id);
|
||||
return;
|
||||
}
|
||||
|
||||
// 立即添加一个AI回复的加载状态消息
|
||||
const loadingMessage = {
|
||||
id: "loading_" + Math.random().toString(36).substring(2, 15),
|
||||
|
|
@ -1242,7 +1147,6 @@ export default {
|
|||
console.log("触发上拉刷新");
|
||||
|
||||
if (!this.currentDMid) return;
|
||||
if (this.isLiveAgentChat) return;
|
||||
|
||||
// 如果已经没有更多数据或正在切换对话或当前对话为空(新建对话),不再触发上拉刷新
|
||||
if (this.noMoreData || this.isSwitchingConversation) {
|
||||
|
|
@ -1299,41 +1203,6 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
sendLiveAgentTextMessage(messageText, localId) {
|
||||
const dialogueManagementId = this.currentDMid || "";
|
||||
const receiverId =
|
||||
(this.vuex_msgUser &&
|
||||
(this.vuex_msgUser.id ||
|
||||
this.vuex_msgUser.Id ||
|
||||
this.vuex_msgUser.receiverId)) ||
|
||||
"";
|
||||
|
||||
if (!dialogueManagementId || !receiverId) {
|
||||
this.$refs.uToast.show({
|
||||
title: "人工会话未初始化,请重新转人工",
|
||||
type: "warning",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const payload = {
|
||||
dialogueManagementId,
|
||||
receiverId,
|
||||
message: messageText,
|
||||
messageType: 0,
|
||||
filePath: "",
|
||||
ip: "",
|
||||
};
|
||||
|
||||
this.$u.api.SendMessage_PrivateApi(payload).then((res) => {
|
||||
if (res && res.succeed) return;
|
||||
this.$refs.uToast.show({
|
||||
title: (res && (res.msg || res.message)) || "发送失败",
|
||||
type: "warning",
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// 获取热门问题
|
||||
hotQARefresh() {
|
||||
console.log("刷新问题");
|
||||
|
|
|
|||
|
|
@ -45,8 +45,6 @@ const store = new Vuex.Store({
|
|||
vuex_version: "1.0.0",
|
||||
// 智能客服消息组列表
|
||||
vuex_aiMessageGroups: [],
|
||||
vuex_aiActiveDMid: "",
|
||||
vuex_isTransferChat: false,
|
||||
// 当前聊天窗口消息列表(数组
|
||||
vuex_msgList: [],
|
||||
// 最近联系人/会话列表
|
||||
|
|
@ -185,40 +183,6 @@ const store = new Vuex.Store({
|
|||
},
|
||||
|
||||
// ===== 智能客服:消息组列表维护(参照 vuex_msgList 维护方式) =====
|
||||
set_AiActiveDMid(state, dmid) {
|
||||
state.vuex_aiActiveDMid = dmid || "";
|
||||
},
|
||||
set_IsTransferChat(state, val) {
|
||||
state.vuex_isTransferChat = !!val;
|
||||
},
|
||||
push_AiLiveAgentMsg(state, msg) {
|
||||
if (!msg) return;
|
||||
const msgId = msg.id || msg.Id;
|
||||
if (!msgId) return;
|
||||
|
||||
const exists = (state.vuex_aiMessageGroups || []).some(
|
||||
(item) => item && item.id === msgId
|
||||
);
|
||||
if (exists) return;
|
||||
|
||||
const userId =
|
||||
(state.vuex_user && (state.vuex_user.Id || state.vuex_user.id)) || "";
|
||||
const senderId = msg.senderId || msg.SenderId || "";
|
||||
const isSelf =
|
||||
userId && senderId && String(userId) === String(senderId);
|
||||
|
||||
state.vuex_aiMessageGroups.push({
|
||||
id: msgId,
|
||||
message: msg.message || msg.Message || "",
|
||||
sendDate: msg.sendDate || msg.SendDate || "",
|
||||
isSend: true,
|
||||
isRead: true,
|
||||
interactMode: isSelf ? 0 : 8,
|
||||
messageType: msg.messageType || msg.MessageType || 0,
|
||||
timeLabel: 0,
|
||||
displayTime: "",
|
||||
});
|
||||
},
|
||||
// 覆盖整个列表
|
||||
push_AiMsgList(state, list) {
|
||||
state.vuex_aiMessageGroups = Array.isArray(list) ? list : [];
|
||||
|
|
@ -329,8 +293,6 @@ const store = new Vuex.Store({
|
|||
state.vuex_userMsgList = [];
|
||||
state.vuex_msgUser = null;
|
||||
state.vuex_msgScrollTop = 0;
|
||||
state.vuex_aiActiveDMid = "";
|
||||
state.vuex_isTransferChat = false;
|
||||
},
|
||||
// 统一登出清理:清除 token 与用户数据,并同步到本地存储
|
||||
// 注意:仅清理与登录态相关的关键字段,避免影响其他持久化数据
|
||||
|
|
@ -344,8 +306,6 @@ const store = new Vuex.Store({
|
|||
state.vuex_userMsgList = [];
|
||||
state.vuex_msgUser = null;
|
||||
state.vuex_msgScrollTop = 0;
|
||||
state.vuex_aiActiveDMid = "";
|
||||
state.vuex_isTransferChat = false;
|
||||
// 同步更新本地持久化
|
||||
saveLifeData("vuex_token", state.vuex_token);
|
||||
saveLifeData("vuex_teacherInfo", state.vuex_teacherInfo);
|
||||
|
|
@ -459,25 +419,19 @@ const store = new Vuex.Store({
|
|||
},
|
||||
|
||||
// 点击聊天记录,切换到该会话
|
||||
selectTeacherChatItem(
|
||||
{ commit, dispatch },
|
||||
{ id, receiverId, navigate = true } = {}
|
||||
) {
|
||||
if (!id || !receiverId) return;
|
||||
selectTeacherChatItem({ commit, dispatch }, { id, receiverId }) {
|
||||
// 清空消息列表,避免旧消息干扰
|
||||
commit("push_MsgList", []);
|
||||
|
||||
return Vue.prototype.$u.api
|
||||
Vue.prototype.$u.api
|
||||
.GetReceiverUserInfoApi({ Id: receiverId })
|
||||
.then((res) => {
|
||||
if (res.succeed && res.data) {
|
||||
commit("set_MsgUser", { ...res.data, dialogueManagementId: id });
|
||||
if (navigate) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/chat/index`,
|
||||
});
|
||||
}
|
||||
return res.data;
|
||||
uni.navigateTo({
|
||||
url: `/pages/chat/index`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue