feat(智能客服): 实现消息组列表的Vuex状态管理及页面集成

This commit is contained in:
yangzhe 2025-12-18 16:13:01 +08:00
parent fc97ec241c
commit f6486a69ea
2 changed files with 142 additions and 80 deletions

View File

@ -128,7 +128,7 @@
<!-- 消息循环渲染 --> <!-- 消息循环渲染 -->
<block <block
v-for="(message, index) in messageGroups" v-for="(message, index) in aiMessageGroups"
:key="'msg-' + index" :key="'msg-' + index"
> >
<!-- 时间 --> <!-- 时间 -->
@ -471,32 +471,6 @@ export default {
"我什么时候能推知道自己是否被录取?", "我什么时候能推知道自己是否被录取?",
], ],
scrollToView: "", scrollToView: "",
// messageGroups
messageGroups: [
// {
// id: "9cac8661-bf09-4b63-ab15-1a0a36b921e0",
// message: "线",
// sendDate: "2025-07-10T15:11:32.886075",
// isSend: true,
// isRead: false,
// interactMode: 0,
// messageType: 0,
// timeLabel: 1,
// displayTime: "15:11",
// },
// {
// id: "02306fc3-c821-4a23-ad66-0bd77d154105",
// message:
// "2025线线2023-2024线\n\n线西www.jxnee.edu.cn0790-6764666/6765666",
// sendDate: "2025-07-10T15:11:32.88644",
// isSend: true,
// isRead: false,
// interactMode: 1,
// messageType: 0,
// timeLabel: 0,
// displayTime: "",
// },
],
scrollTop: 0, scrollTop: 0,
messageValue: "", // messageValue: "", //
@ -511,11 +485,16 @@ export default {
return "/static/common/images/avatar.png"; return "/static/common/images/avatar.png";
}, },
aiMessageGroups() {
return Array.isArray(this.vuex_aiMessageGroups)
? this.vuex_aiMessageGroups
: [];
},
}, },
watch: { watch: {
// //
messageGroups: { aiMessageGroups: {
handler() { handler() {
// //
if (!this.isLoadingMore) { if (!this.isLoadingMore) {
@ -559,7 +538,7 @@ export default {
this.isSwitchingConversation = true; this.isSwitchingConversation = true;
this.currentConversationId = conversationId; this.currentConversationId = conversationId;
this.currentDMid = dmid; this.currentDMid = dmid;
this.messageGroups = []; this.$store.commit("push_AiMsgList", []);
this.pageQuery.PageIndex = 1; this.pageQuery.PageIndex = 1;
this.isLoadingMore = false; this.isLoadingMore = false;
this.noMoreData = false; this.noMoreData = false;
@ -699,14 +678,15 @@ export default {
this.isLoadingMore = false; this.isLoadingMore = false;
this.isTransferSubmitting = false; this.isTransferSubmitting = false;
this.messageGroups = (this.messageGroups || []).filter( const nextList = this.aiMessageGroups.filter(
(m) => !(m && m.customType === "transferCard") (m) => !(m && m.customType === "transferCard")
); );
this.messageGroups.push(this.createLocalUserTextMessage("转人工")); nextList.push(this.createLocalUserTextMessage("转人工"));
const card = this.createTransferCardMessage(); const card = this.createTransferCardMessage();
this.activeTransferCardId = card.id; this.activeTransferCardId = card.id;
this.messageGroups.push(card); nextList.push(card);
this.$store.commit("push_AiMsgList", nextList);
}, },
getTransferCardTip(message) { getTransferCardTip(message) {
@ -718,21 +698,22 @@ export default {
handleTransferTypeSelect(consultationType) { handleTransferTypeSelect(consultationType) {
const cardId = this.activeTransferCardId; const cardId = this.activeTransferCardId;
const findCardIndex = () => { const findCardIndex = (list) => {
if (cardId) { if (cardId) {
const byId = this.messageGroups.findIndex( const byId = list.findIndex(
(m) => m && m.id === cardId (m) => m && m.id === cardId
); );
if (byId >= 0) return byId; if (byId >= 0) return byId;
} }
return this.messageGroups.findIndex( return list.findIndex(
(m) => m && m.customType === "transferCard" (m) => m && m.customType === "transferCard"
); );
}; };
const idx = findCardIndex(); const list = this.aiMessageGroups;
const idx = findCardIndex(list);
if (idx < 0) return; if (idx < 0) return;
const current = this.messageGroups[idx] || {}; const current = list[idx] || {};
if (this.isTransferSubmitting || current.transferStatus === "done") return; if (this.isTransferSubmitting || current.transferStatus === "done") return;
const next = { const next = {
@ -741,7 +722,9 @@ export default {
selectedConsultationType: consultationType, selectedConsultationType: consultationType,
transferTipText: "", transferTipText: "",
}; };
this.$set(this.messageGroups, idx, next); const nextList = list.slice();
nextList.splice(idx, 1, next);
this.$store.commit("push_AiMsgList", nextList);
this.isTransferSubmitting = true; this.isTransferSubmitting = true;
const params = { const params = {
@ -754,28 +737,51 @@ export default {
params.dialogueManagementId = this.currentDMid; params.dialogueManagementId = this.currentDMid;
} }
this.$u.api.TransferToALiveAgentApi(params).then((res) => { this.$u.api
.TransferToALiveAgentApi(params)
.then((res) => {
this.isTransferSubmitting = false; this.isTransferSubmitting = false;
const nextIdx = findCardIndex(); const latestList = this.aiMessageGroups;
const nextIdx = findCardIndex(latestList);
if (nextIdx < 0) return; if (nextIdx < 0) return;
const succeed = res && res.succeed !== false; const succeed = res && res.succeed !== false;
const serverTip = const serverTip =
(res && res.data && res.data.message) || (res && res.error) || ""; (res && res.data && res.data.message) ||
(res && res.error) ||
"";
if (!succeed) { if (!succeed) {
const updated = { const updated = {
...this.messageGroups[nextIdx], ...latestList[nextIdx],
transferStatus: "idle", transferStatus: "idle",
transferTipText: serverTip, transferTipText: serverTip,
}; };
this.$set(this.messageGroups, nextIdx, updated); const updatedList = latestList.slice();
updatedList.splice(nextIdx, 1, updated);
this.$store.commit("push_AiMsgList", updatedList);
return; return;
} }
const updated = { const updated = {
...this.messageGroups[nextIdx], ...latestList[nextIdx],
transferStatus: "done", transferStatus: "done",
transferTipText: serverTip, transferTipText: serverTip,
}; };
this.$set(this.messageGroups, nextIdx, updated); const updatedList = latestList.slice();
updatedList.splice(nextIdx, 1, updated);
this.$store.commit("push_AiMsgList", updatedList);
})
.catch(() => {
this.isTransferSubmitting = false;
const latestList = this.aiMessageGroups;
const nextIdx = findCardIndex(latestList);
if (nextIdx < 0) return;
const updated = {
...latestList[nextIdx],
transferStatus: "idle",
transferTipText: "转人工失败,请稍后重试",
};
const updatedList = latestList.slice();
updatedList.splice(nextIdx, 1, updated);
this.$store.commit("push_AiMsgList", updatedList);
}); });
}, },
@ -805,7 +811,7 @@ export default {
}; };
// //
this.messageGroups.push(userMessage); this.$store.commit("push_AiMsg", userMessage);
this.messageValue = ""; this.messageValue = "";
// AI // AI
@ -823,7 +829,7 @@ export default {
}; };
// //
this.messageGroups.push(loadingMessage); this.$store.commit("push_AiMsg", loadingMessage);
const params = { const params = {
query: sendMessage, query: sendMessage,
@ -844,7 +850,7 @@ export default {
this.currentDMid = data.dmid; this.currentDMid = data.dmid;
// //
this.messageGroups = this.messageGroups.filter( const baseList = this.aiMessageGroups.filter(
(msg) => !msg.isLoading (msg) => !msg.isLoading
); );
@ -864,13 +870,13 @@ export default {
}; };
// //
this.messageGroups.push(aiMessage); this.$store.commit("push_AiMsgList", baseList.concat([aiMessage]));
}) })
.catch((error) => { .catch((error) => {
console.error("API请求失败:", error); console.error("API请求失败:", error);
// //
this.messageGroups = this.messageGroups.filter( const baseList = this.aiMessageGroups.filter(
(msg) => !msg.isLoading (msg) => !msg.isLoading
); );
@ -887,7 +893,10 @@ export default {
displayTime: "", displayTime: "",
}; };
this.messageGroups.push(errorMessage); this.$store.commit(
"push_AiMsgList",
baseList.concat([errorMessage])
);
}); });
}, },
@ -918,7 +927,7 @@ export default {
}; };
// //
this.messageGroups.push(userMessage); this.$store.commit("push_AiMsg", userMessage);
// AI // AI
const loadingMessage = { const loadingMessage = {
@ -935,7 +944,7 @@ export default {
}; };
// //
this.messageGroups.push(loadingMessage); this.$store.commit("push_AiMsg", loadingMessage);
const params = { const params = {
id: item.id, id: item.id,
@ -953,7 +962,7 @@ export default {
const data = res.data.entityInfo; const data = res.data.entityInfo;
// //
this.messageGroups = this.messageGroups.filter( const baseList = this.aiMessageGroups.filter(
(msg) => !msg.isLoading (msg) => !msg.isLoading
); );
@ -973,11 +982,15 @@ export default {
}; };
// //
this.messageGroups.push(aiMessage); this.$store.commit(
"push_AiMsgList",
baseList.concat([aiMessage])
);
} else { } else {
// //
this.messageGroups = this.messageGroups.filter( this.$store.commit(
(msg) => !msg.isLoading "push_AiMsgList",
this.aiMessageGroups.filter((msg) => !msg.isLoading)
); );
} }
}) })
@ -985,7 +998,7 @@ export default {
console.error("API请求失败:", error); console.error("API请求失败:", error);
// //
this.messageGroups = this.messageGroups.filter( const baseList = this.aiMessageGroups.filter(
(msg) => !msg.isLoading (msg) => !msg.isLoading
); );
@ -1002,7 +1015,10 @@ export default {
displayTime: "", displayTime: "",
}; };
this.messageGroups.push(errorMessage); this.$store.commit(
"push_AiMsgList",
baseList.concat([errorMessage])
);
}); });
}, },
@ -1022,7 +1038,7 @@ export default {
this.isSwitchingConversation = true; this.isSwitchingConversation = true;
// //
this.messageGroups = []; this.$store.commit("push_AiMsgList", []);
this.pageQuery.PageIndex = 1; this.pageQuery.PageIndex = 1;
this.isLoadingMore = false; this.isLoadingMore = false;
this.noMoreData = false; this.noMoreData = false;
@ -1056,7 +1072,10 @@ export default {
const currentList = res.item2 || []; const currentList = res.item2 || [];
// sendDate(interactMode=0) // sendDate(interactMode=0)
this.messageGroups = this.sortMessages(currentList); this.$store.commit(
"push_AiMsgList",
this.sortMessages(currentList)
);
}) })
.finally(() => { .finally(() => {
// //
@ -1091,11 +1110,17 @@ export default {
}) })
.then((res3) => { .then((res3) => {
const prevList = res3?.item2 || []; const prevList = res3?.item2 || [];
this.messageGroups = this.sortMessages(prevList); this.$store.commit(
"push_AiMsgList",
this.sortMessages(prevList)
);
this.pageQuery.PageIndex = prevIndex; this.pageQuery.PageIndex = prevIndex;
}); });
} else { } else {
this.messageGroups = this.sortMessages(currentList); this.$store.commit(
"push_AiMsgList",
this.sortMessages(currentList)
);
} }
}); });
}, },
@ -1156,10 +1181,10 @@ export default {
// sendDate(interactMode=0) // sendDate(interactMode=0)
const nextPageMessageGroups = sortChatMessages(res.item2 || []); const nextPageMessageGroups = sortChatMessages(res.item2 || []);
this.messageGroups = [ this.$store.commit(
...nextPageMessageGroups, "prepend_AiMsgList",
...this.messageGroups, nextPageMessageGroups
]; );
}) })
.finally(() => { .finally(() => {
setTimeout(() => { setTimeout(() => {

View File

@ -43,6 +43,7 @@ const store = new Vuex.Store({
vuex_token: lifeData.vuex_token ? lifeData.vuex_token : "", vuex_token: lifeData.vuex_token ? lifeData.vuex_token : "",
// 如果vuex_version无需保存到本地永久存储无需lifeData.vuex_version方式 // 如果vuex_version无需保存到本地永久存储无需lifeData.vuex_version方式
vuex_version: "1.0.0", vuex_version: "1.0.0",
// 智能客服消息组列表
vuex_aiMessageGroups: [], vuex_aiMessageGroups: [],
// 当前聊天窗口消息列表(数组 // 当前聊天窗口消息列表(数组
vuex_msgList: [], vuex_msgList: [],
@ -178,6 +179,42 @@ const store = new Vuex.Store({
if (!msg) return; if (!msg) return;
state.vuex_msgList.unshift(msg); state.vuex_msgList.unshift(msg);
}, },
// ===== 智能客服:消息组列表维护(参照 vuex_msgList 维护方式) =====
// 覆盖整个列表
push_AiMsgList(state, list) {
state.vuex_aiMessageGroups = Array.isArray(list) ? list : [];
},
// 追加历史消息到头部(分页加载)
prepend_AiMsgList(state, list) {
const prev = state.vuex_aiMessageGroups || [];
const next = Array.isArray(list) ? list : [];
const merged = [...next, ...prev];
const seen = new Set();
state.vuex_aiMessageGroups = merged.filter((item) => {
const id = item && item.id;
if (!id) return true;
if (seen.has(id)) return false;
seen.add(id);
return true;
});
},
// 推送一条新消息(去重)
push_AiMsg(state, msg) {
if (!msg || !msg.id) return;
const exists = (state.vuex_aiMessageGroups || []).some(
(item) => item && item.id === msg.id
);
if (!exists) {
state.vuex_aiMessageGroups.push(msg);
}
},
// 插入一条消息到头部
unshift_AiMsg(state, msg) {
if (!msg) return;
state.vuex_aiMessageGroups.unshift(msg);
},
// 更新置顶状态(本地) // 更新置顶状态(本地)
update_TopState(state, { friendId, isTop }) { update_TopState(state, { friendId, isTop }) {
state.vuex_userMsgList = (state.vuex_userMsgList || []).map((item) => { state.vuex_userMsgList = (state.vuex_userMsgList || []).map((item) => {