Merge branch 'main' of http://sl.vrgon.com:3000/JiXinHui/YingXingAI
This commit is contained in:
commit
0a3a521a32
|
|
@ -236,18 +236,21 @@ const install = (Vue, vm) => {
|
||||||
// 获取消息接收方用户信息
|
// 获取消息接收方用户信息
|
||||||
let GetReceiverUserInfoApi = (params = {}) =>
|
let GetReceiverUserInfoApi = (params = {}) =>
|
||||||
vm.$u.get("api/Dialogue/GetReceiverUserInfo", params);
|
vm.$u.get("api/Dialogue/GetReceiverUserInfo", params);
|
||||||
// 置顶一个会话
|
// 置顶一个会话
|
||||||
let OverheadOneDialogueApi = (params = {}) =>
|
let OverheadOneDialogueApi = (params = {}) =>
|
||||||
vm.$u.post("api/Dialogue/OverheadOneDialogue", params);
|
vm.$u.post("api/Dialogue/OverheadOneDialogue", params);
|
||||||
// 将会话消息标记为已读
|
// 将会话消息标记为已读
|
||||||
let ReadMessageApi = (params = {}) =>
|
let ReadMessageApi = (params = {}) =>
|
||||||
vm.$u.post("api/Dialogue/ReadMessage", params);
|
vm.$u.post("api/Dialogue/ReadMessage", params);
|
||||||
// 删除会话
|
// 删除会话
|
||||||
let DeleteDialogueApi = (params = {}) =>
|
let DeleteDialogueApi = (params = {}) =>
|
||||||
vm.$u.post("api/Dialogue/DeleteDialogue", params);
|
vm.$u.post("api/Dialogue/DeleteDialogue", params);
|
||||||
|
// 转人工服务
|
||||||
|
let TransferToALiveAgentApi = (params = {}) =>
|
||||||
|
vm.$u.post("api/Dialogue/TransferToALiveAgent", params);
|
||||||
|
|
||||||
// 将各个定义的接口名称,统一放进对象挂载到vm.$u.api(因为vm就是this,也即this.$u.api)下
|
// 将各个定义的接口名称,统一放进对象挂载到vm.$u.api(因为vm就是this,也即this.$u.api)下
|
||||||
vm.$u.api = {
|
vm.$u.api = {
|
||||||
UploadSingleImage,
|
UploadSingleImage,
|
||||||
getTeacherInfo,
|
getTeacherInfo,
|
||||||
getData,
|
getData,
|
||||||
|
|
@ -306,16 +309,17 @@ const install = (Vue, vm) => {
|
||||||
UpdateUserApi,
|
UpdateUserApi,
|
||||||
GetTeacherListApi,
|
GetTeacherListApi,
|
||||||
GetDialogueListApi,
|
GetDialogueListApi,
|
||||||
GetDialogueList_UserApi,
|
GetDialogueList_UserApi,
|
||||||
AddDialogueApi,
|
AddDialogueApi,
|
||||||
SendMessage_PrivateApi,
|
SendMessage_PrivateApi,
|
||||||
GetChatHistoryDataApi,
|
GetChatHistoryDataApi,
|
||||||
GetReceiverUserInfoApi,
|
GetReceiverUserInfoApi,
|
||||||
OverheadOneDialogueApi,
|
OverheadOneDialogueApi,
|
||||||
ReadMessageApi,
|
ReadMessageApi,
|
||||||
DeleteDialogueApi,
|
DeleteDialogueApi,
|
||||||
};
|
TransferToALiveAgentApi,
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
install,
|
install,
|
||||||
|
|
|
||||||
|
|
@ -374,13 +374,6 @@ export default {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// 格式化时间
|
|
||||||
formatTime(date) {
|
|
||||||
const hours = date.getHours().toString().padStart(2, "0");
|
|
||||||
const minutes = date.getMinutes().toString().padStart(2, "0");
|
|
||||||
return `${hours}:${minutes}`;
|
|
||||||
},
|
|
||||||
|
|
||||||
// 是否显示时间
|
// 是否显示时间
|
||||||
isShowTime(index) {
|
isShowTime(index) {
|
||||||
return shouldShowTime(this.vuex_msgList, index);
|
return shouldShowTime(this.vuex_msgList, index);
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@
|
||||||
<view class="date-header">{{ group.id }}</view>
|
<view class="date-header">{{ group.id }}</view>
|
||||||
|
|
||||||
<view v-for="item in group.conversation" :key="item.id">
|
<view v-for="item in group.conversation" :key="item.id">
|
||||||
<uni-swipe-action ref="swipeActionRef">
|
<uni-swipe-action :ref="'swipe-' + item.id">
|
||||||
<uni-swipe-action-item
|
<uni-swipe-action-item
|
||||||
:disabled="isBatchDeleteMode"
|
:disabled="isBatchDeleteMode"
|
||||||
:threshold="0.3"
|
:threshold="0.3"
|
||||||
|
|
@ -123,7 +123,10 @@
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 批量删除操作栏 -->
|
<!-- 批量删除操作栏 -->
|
||||||
<view class="batch-actions" v-if="isBatchDeleteMode && currentHistoryItems.length">
|
<view
|
||||||
|
class="batch-actions"
|
||||||
|
v-if="isBatchDeleteMode && currentHistoryItems.length"
|
||||||
|
>
|
||||||
<view class="select-all-container" @click="toggleSelectAll">
|
<view class="select-all-container" @click="toggleSelectAll">
|
||||||
<view class="checkbox" :class="{ checked: selectAll }">
|
<view class="checkbox" :class="{ checked: selectAll }">
|
||||||
<text class="checkmark" v-if="selectAll">✓</text>
|
<text class="checkmark" v-if="selectAll">✓</text>
|
||||||
|
|
@ -164,6 +167,7 @@ export default {
|
||||||
chatHistoryAI: [], // ai咨询历史记录
|
chatHistoryAI: [], // ai咨询历史记录
|
||||||
chatHistoryTeacher: [], // 人工咨询历史记录
|
chatHistoryTeacher: [], // 人工咨询历史记录
|
||||||
openedItems: {}, // 记录每个项目的滑动状态
|
openedItems: {}, // 记录每个项目的滑动状态
|
||||||
|
openedSwipeId: "", // 当前展开的侧滑项 id
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -207,16 +211,9 @@ export default {
|
||||||
|
|
||||||
// 重置滑动状态
|
// 重置滑动状态
|
||||||
closeAllSwipeActions() {
|
closeAllSwipeActions() {
|
||||||
const swipeActionRefs = this.$refs.swipeActionRef || [];
|
const ids = this.currentHistoryItemIds || [];
|
||||||
const refs = Array.isArray(swipeActionRefs)
|
ids.forEach((id) => this.closeSwipeActionById(id));
|
||||||
? swipeActionRefs
|
this.openedSwipeId = "";
|
||||||
: [swipeActionRefs];
|
|
||||||
|
|
||||||
refs.forEach((ref) => {
|
|
||||||
if (ref && typeof ref.closeAll === "function") {
|
|
||||||
ref.closeAll();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// 清空 openedItems 并调用 closeAllSwipeActions()
|
// 清空 openedItems 并调用 closeAllSwipeActions()
|
||||||
|
|
@ -225,6 +222,16 @@ export default {
|
||||||
this.closeAllSwipeActions();
|
this.closeAllSwipeActions();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
closeSwipeActionById(itemId) {
|
||||||
|
if (!itemId) return;
|
||||||
|
const swipeRef = this.$refs[`swipe-${itemId}`];
|
||||||
|
const ref = Array.isArray(swipeRef) ? swipeRef[0] : swipeRef;
|
||||||
|
if (ref && typeof ref.closeAll === "function") {
|
||||||
|
ref.closeAll();
|
||||||
|
}
|
||||||
|
this.$set(this.openedItems, itemId, "none");
|
||||||
|
},
|
||||||
|
|
||||||
// 获取ai历史记录
|
// 获取ai历史记录
|
||||||
async getChatHistoryList() {
|
async getChatHistoryList() {
|
||||||
this.$u.api.GetConversationPage().then((res) => {
|
this.$u.api.GetConversationPage().then((res) => {
|
||||||
|
|
@ -465,6 +472,16 @@ export default {
|
||||||
// 处理滑动操作变化
|
// 处理滑动操作变化
|
||||||
handleSwipeChange(e, itemId) {
|
handleSwipeChange(e, itemId) {
|
||||||
this.$set(this.openedItems, itemId, e);
|
this.$set(this.openedItems, itemId, e);
|
||||||
|
if (e === "right" || e === "left") {
|
||||||
|
if (this.openedSwipeId && this.openedSwipeId !== itemId) {
|
||||||
|
this.closeSwipeActionById(this.openedSwipeId);
|
||||||
|
}
|
||||||
|
this.openedSwipeId = itemId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e === "none" && this.openedSwipeId === itemId) {
|
||||||
|
this.openedSwipeId = "";
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 处理单个删除操作
|
// 处理单个删除操作
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@
|
||||||
|
|
||||||
<!-- 消息循环渲染 -->
|
<!-- 消息循环渲染 -->
|
||||||
<block
|
<block
|
||||||
v-for="(message, index) in messageGroups"
|
v-for="(message, index) in aiMessageGroups"
|
||||||
:key="'msg-' + index"
|
:key="'msg-' + index"
|
||||||
>
|
>
|
||||||
<!-- 时间 -->
|
<!-- 时间 -->
|
||||||
|
|
@ -136,11 +136,77 @@
|
||||||
{{ message.displayTime }}
|
{{ message.displayTime }}
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 转人工选择卡片(独立消息,不属于AI回复,不展示头像/反馈) -->
|
||||||
|
<view
|
||||||
|
class="message-transfer"
|
||||||
|
v-if="message.customType === 'transferCard'"
|
||||||
|
:id="'msg-' + message.id"
|
||||||
|
>
|
||||||
|
<view class="transfer-card">
|
||||||
|
<view class="transfer-card-title">
|
||||||
|
请选择您要咨询的类型,以便系统为您转接对应的客服
|
||||||
|
</view>
|
||||||
|
<view class="transfer-card-options">
|
||||||
|
<view
|
||||||
|
class="transfer-option"
|
||||||
|
:class="{
|
||||||
|
selected: message.selectedConsultationType === 1,
|
||||||
|
disabled:
|
||||||
|
isTransferSubmitting ||
|
||||||
|
message.transferStatus === 'done',
|
||||||
|
}"
|
||||||
|
@click.stop="handleTransferTypeSelect(1)"
|
||||||
|
>
|
||||||
|
<u-icon
|
||||||
|
name="account"
|
||||||
|
size="44"
|
||||||
|
:color="
|
||||||
|
message.selectedConsultationType === 1
|
||||||
|
? '#4A6CF7'
|
||||||
|
: '#C0C4CC'
|
||||||
|
"
|
||||||
|
></u-icon>
|
||||||
|
<text class="transfer-option-text">招生咨询</text>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="transfer-option"
|
||||||
|
:class="{
|
||||||
|
selected: message.selectedConsultationType === 0,
|
||||||
|
disabled:
|
||||||
|
isTransferSubmitting ||
|
||||||
|
message.transferStatus === 'done',
|
||||||
|
}"
|
||||||
|
@click.stop="handleTransferTypeSelect(0)"
|
||||||
|
>
|
||||||
|
<u-icon
|
||||||
|
name="account"
|
||||||
|
size="44"
|
||||||
|
:color="
|
||||||
|
message.selectedConsultationType === 0
|
||||||
|
? '#4A6CF7'
|
||||||
|
: '#C0C4CC'
|
||||||
|
"
|
||||||
|
></u-icon>
|
||||||
|
<text class="transfer-option-text">迎新咨询</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="transfer-card-status"
|
||||||
|
v-if="
|
||||||
|
isTransferSubmitting ||
|
||||||
|
!!message.transferTipText
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ getTransferCardTip(message) }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 用户消息 -->
|
<!-- 用户消息 -->
|
||||||
<!-- 0 用户消息 -->
|
<!-- 0 用户消息 -->
|
||||||
<view
|
<view
|
||||||
class="message-right"
|
class="message-right"
|
||||||
v-if="message.interactMode === 0"
|
v-else-if="message.interactMode === 0"
|
||||||
:id="'msg-' + message.id"
|
:id="'msg-' + message.id"
|
||||||
>
|
>
|
||||||
<view class="message-content">
|
<view class="message-content">
|
||||||
|
|
@ -157,7 +223,9 @@
|
||||||
<!-- 1 Ai回复 3 热门回复 -->
|
<!-- 1 Ai回复 3 热门回复 -->
|
||||||
<view
|
<view
|
||||||
class="message-left"
|
class="message-left"
|
||||||
v-if="message.interactMode === 1 || message.interactMode === 3"
|
v-else-if="
|
||||||
|
message.interactMode === 1 || message.interactMode === 3
|
||||||
|
"
|
||||||
:id="'msg-' + message.id"
|
:id="'msg-' + message.id"
|
||||||
>
|
>
|
||||||
<image
|
<image
|
||||||
|
|
@ -285,6 +353,11 @@ import AdvicePhone from "@/components/AdvicePhone.vue";
|
||||||
import PerfectInfo from "@/components/PerfectInfo.vue";
|
import PerfectInfo from "@/components/PerfectInfo.vue";
|
||||||
import ChatHistory from "@/components/ChatHistory.vue"; // 导入新组件
|
import ChatHistory from "@/components/ChatHistory.vue"; // 导入新组件
|
||||||
import HeaderBar from "@/components/HeaderBar.vue"; // 导入头部组件
|
import HeaderBar from "@/components/HeaderBar.vue"; // 导入头部组件
|
||||||
|
import {
|
||||||
|
processChatMessageContent,
|
||||||
|
scrollToBottomByContentHeight,
|
||||||
|
sortChatMessages,
|
||||||
|
} from "@/utils/chat.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -301,6 +374,8 @@ export default {
|
||||||
isChat: false,
|
isChat: false,
|
||||||
currentConversationId: "", // 当前对话的ID
|
currentConversationId: "", // 当前对话的ID
|
||||||
currentDMid: "", // 当前对话的DMId
|
currentDMid: "", // 当前对话的DMId
|
||||||
|
activeTransferCardId: "", // 当前选中的转人工卡片ID
|
||||||
|
isTransferSubmitting: false, // 转人工请求中(用于失败时不改messageGroups)
|
||||||
advicePhoneShow: false,
|
advicePhoneShow: false,
|
||||||
perfectInfoShow: false,
|
perfectInfoShow: false,
|
||||||
isLoading: false, // loadingMore
|
isLoading: false, // loadingMore
|
||||||
|
|
@ -396,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.cn)或者直接联系招生办(电话:0790-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: "", // 输入框内容
|
||||||
|
|
@ -436,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) {
|
||||||
|
|
@ -484,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;
|
||||||
|
|
@ -550,28 +604,9 @@ export default {
|
||||||
// 新建对话时不执行滚动
|
// 新建对话时不执行滚动
|
||||||
if (this.isLoadingMore) return;
|
if (this.isLoadingMore) return;
|
||||||
|
|
||||||
// 使用nextTick确保DOM已更新
|
scrollToBottomByContentHeight(this, {
|
||||||
this.$nextTick(() => {
|
selector: ".chat-content",
|
||||||
// setTimeout(() => {
|
extraOffset: 200,
|
||||||
const query = uni.createSelectorQuery().in(this);
|
|
||||||
query
|
|
||||||
.select(".chat-content")
|
|
||||||
.boundingClientRect((data) => {
|
|
||||||
if (data) {
|
|
||||||
console.log("chat-content高度:", data.height);
|
|
||||||
|
|
||||||
// 同时设置scrollTop和scrollToView
|
|
||||||
this.scrollTop = data.height + 200;
|
|
||||||
// if (this.messageGroups.length > 0) {
|
|
||||||
// const lastMessage =
|
|
||||||
// this.messageGroups[this.messageGroups.length - 1];
|
|
||||||
// this.scrollToView = "msg-" + lastMessage.id;
|
|
||||||
// console.log("设置scrollToView:", this.scrollToView);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.exec();
|
|
||||||
// }, 300);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleFeatureClick(item) {
|
handleFeatureClick(item) {
|
||||||
|
|
@ -580,6 +615,11 @@ export default {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item.title === "转人工") {
|
||||||
|
this.handleTransferEntryClick();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (item.title === "电话咨询") {
|
if (item.title === "电话咨询") {
|
||||||
this.advicePhoneShow = true;
|
this.advicePhoneShow = true;
|
||||||
return;
|
return;
|
||||||
|
|
@ -598,6 +638,153 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
createLocalUserTextMessage(messageText) {
|
||||||
|
return {
|
||||||
|
id: Math.random().toString(36).substring(2, 15),
|
||||||
|
message: messageText,
|
||||||
|
sendDate: "",
|
||||||
|
isSend: true,
|
||||||
|
isRead: false,
|
||||||
|
interactMode: 0,
|
||||||
|
messageType: 0,
|
||||||
|
timeLabel: 0,
|
||||||
|
displayTime: "",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
createTransferCardMessage() {
|
||||||
|
return {
|
||||||
|
id: "transfer_" + Math.random().toString(36).substring(2, 15),
|
||||||
|
message: "",
|
||||||
|
sendDate: "",
|
||||||
|
isSend: true,
|
||||||
|
isRead: false,
|
||||||
|
interactMode: 1,
|
||||||
|
messageType: 0,
|
||||||
|
timeLabel: 0,
|
||||||
|
displayTime: "",
|
||||||
|
customType: "transferCard",
|
||||||
|
transferStatus: "idle",
|
||||||
|
selectedConsultationType: null,
|
||||||
|
transferTipText: "",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
handleTransferEntryClick() {
|
||||||
|
if (!this.isChat) {
|
||||||
|
this.resetChatState();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isLoadingMore = false;
|
||||||
|
this.isTransferSubmitting = false;
|
||||||
|
|
||||||
|
const nextList = this.aiMessageGroups.filter(
|
||||||
|
(m) => !(m && m.customType === "transferCard")
|
||||||
|
);
|
||||||
|
|
||||||
|
nextList.push(this.createLocalUserTextMessage("转人工"));
|
||||||
|
const card = this.createTransferCardMessage();
|
||||||
|
this.activeTransferCardId = card.id;
|
||||||
|
nextList.push(card);
|
||||||
|
this.$store.commit("push_AiMsgList", nextList);
|
||||||
|
},
|
||||||
|
|
||||||
|
getTransferCardTip(message) {
|
||||||
|
if (!message) return "";
|
||||||
|
if (this.isTransferSubmitting) return "正在为您转接人工客服,请稍等...";
|
||||||
|
if (message.transferTipText) return message.transferTipText;
|
||||||
|
return "";
|
||||||
|
},
|
||||||
|
|
||||||
|
handleTransferTypeSelect(consultationType) {
|
||||||
|
const cardId = this.activeTransferCardId;
|
||||||
|
const findCardIndex = (list) => {
|
||||||
|
if (cardId) {
|
||||||
|
const byId = list.findIndex(
|
||||||
|
(m) => m && m.id === cardId
|
||||||
|
);
|
||||||
|
if (byId >= 0) return byId;
|
||||||
|
}
|
||||||
|
return list.findIndex(
|
||||||
|
(m) => m && m.customType === "transferCard"
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const list = this.aiMessageGroups;
|
||||||
|
const idx = findCardIndex(list);
|
||||||
|
if (idx < 0) return;
|
||||||
|
|
||||||
|
const current = list[idx] || {};
|
||||||
|
if (this.isTransferSubmitting || current.transferStatus === "done") return;
|
||||||
|
|
||||||
|
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 = {
|
||||||
|
consultationType,
|
||||||
|
message: "转人工",
|
||||||
|
ip: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.currentDMid) {
|
||||||
|
params.dialogueManagementId = this.currentDMid;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) ||
|
||||||
|
"";
|
||||||
|
if (!succeed) {
|
||||||
|
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 updated = {
|
||||||
|
...latestList[nextIdx],
|
||||||
|
transferStatus: "done",
|
||||||
|
transferTipText: serverTip,
|
||||||
|
};
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
// 修改发送消息的方法
|
// 修改发送消息的方法
|
||||||
sendMessageFn() {
|
sendMessageFn() {
|
||||||
if (!this.messageValue) {
|
if (!this.messageValue) {
|
||||||
|
|
@ -624,7 +811,7 @@ export default {
|
||||||
};
|
};
|
||||||
|
|
||||||
// 添加到消息列表
|
// 添加到消息列表
|
||||||
this.messageGroups.push(userMessage);
|
this.$store.commit("push_AiMsg", userMessage);
|
||||||
this.messageValue = "";
|
this.messageValue = "";
|
||||||
|
|
||||||
// 立即添加一个AI回复的加载状态消息
|
// 立即添加一个AI回复的加载状态消息
|
||||||
|
|
@ -642,7 +829,7 @@ export default {
|
||||||
};
|
};
|
||||||
|
|
||||||
// 添加加载状态消息到列表
|
// 添加加载状态消息到列表
|
||||||
this.messageGroups.push(loadingMessage);
|
this.$store.commit("push_AiMsg", loadingMessage);
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
query: sendMessage,
|
query: sendMessage,
|
||||||
|
|
@ -663,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
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -683,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
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -706,7 +893,10 @@ export default {
|
||||||
displayTime: "",
|
displayTime: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
this.messageGroups.push(errorMessage);
|
this.$store.commit(
|
||||||
|
"push_AiMsgList",
|
||||||
|
baseList.concat([errorMessage])
|
||||||
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -737,7 +927,7 @@ export default {
|
||||||
};
|
};
|
||||||
|
|
||||||
// 添加到消息列表
|
// 添加到消息列表
|
||||||
this.messageGroups.push(userMessage);
|
this.$store.commit("push_AiMsg", userMessage);
|
||||||
|
|
||||||
// 立即添加一个AI回复的加载状态消息
|
// 立即添加一个AI回复的加载状态消息
|
||||||
const loadingMessage = {
|
const loadingMessage = {
|
||||||
|
|
@ -754,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,
|
||||||
|
|
@ -772,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
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -792,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)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -804,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
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -821,17 +1015,13 @@ export default {
|
||||||
displayTime: "",
|
displayTime: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
this.messageGroups.push(errorMessage);
|
this.$store.commit(
|
||||||
|
"push_AiMsgList",
|
||||||
|
baseList.concat([errorMessage])
|
||||||
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// 格式化时间的辅助方法
|
|
||||||
formatTime(date) {
|
|
||||||
const hours = date.getHours().toString().padStart(2, "0");
|
|
||||||
const minutes = date.getMinutes().toString().padStart(2, "0");
|
|
||||||
return `${hours}:${minutes}`;
|
|
||||||
},
|
|
||||||
|
|
||||||
// 处理选中的对话
|
// 处理选中的对话
|
||||||
handleSelectConversation(data) {
|
handleSelectConversation(data) {
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
|
|
@ -848,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;
|
||||||
|
|
@ -859,52 +1049,12 @@ export default {
|
||||||
|
|
||||||
// 处理消息内容,如果是JSON格式则解析并格式化
|
// 处理消息内容,如果是JSON格式则解析并格式化
|
||||||
processMessageContent(message) {
|
processMessageContent(message) {
|
||||||
try {
|
return processChatMessageContent(message);
|
||||||
// 尝试解析 JSON
|
|
||||||
const parsed = JSON.parse(message);
|
|
||||||
|
|
||||||
// 如果是对象且包含特定字段,进行格式化
|
|
||||||
if (typeof parsed === "object" && parsed !== null) {
|
|
||||||
let content = "";
|
|
||||||
|
|
||||||
// 提取字段
|
|
||||||
const { answerTypeLabel, imageUrl, nearbyPaths } = parsed;
|
|
||||||
|
|
||||||
// 拼接内容,如果有值则添加并换行
|
|
||||||
if (answerTypeLabel) content += `${answerTypeLabel}\n`;
|
|
||||||
if (imageUrl) content += `${imageUrl}\n`;
|
|
||||||
if (nearbyPaths) content += `${nearbyPaths}\n`;
|
|
||||||
|
|
||||||
// 如果提取到了内容,返回处理后的文本;否则返回原文本(避免误判)
|
|
||||||
// 去除末尾多余的换行符
|
|
||||||
return content ? content.trim() : message;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// 解析失败,说明不是JSON格式,直接返回原消息
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
return message;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// 公共排序:按时间升序;时间相同,用户消息(interactMode=0)在前
|
// 公共排序:按时间升序;时间相同,用户消息(interactMode=0)在前
|
||||||
sortMessages(list = []) {
|
sortMessages(list = []) {
|
||||||
const processedList = (list || []).map((item) => {
|
return sortChatMessages(list);
|
||||||
// 对每条消息进行处理
|
|
||||||
return {
|
|
||||||
...item,
|
|
||||||
message: this.processMessageContent(item.message),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
// console.log("processedList", processedList);
|
|
||||||
|
|
||||||
return processedList.sort((a, b) => {
|
|
||||||
const timeA = new Date(a.sendDate).getTime();
|
|
||||||
const timeB = new Date(b.sendDate).getTime();
|
|
||||||
if (timeA === timeB) return a.interactMode - b.interactMode;
|
|
||||||
return timeA - timeB;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// 刷新当前对话的消息详情
|
// 刷新当前对话的消息详情
|
||||||
|
|
@ -922,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(() => {
|
||||||
// 延迟重置切换对话标志位,确保滚动事件处理完成
|
// 延迟重置切换对话标志位,确保滚动事件处理完成
|
||||||
|
|
@ -957,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)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
@ -1020,23 +1179,12 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将消息按sendDate升序排列,时间相同时用户消息(interactMode=0)排在前面
|
// 将消息按sendDate升序排列,时间相同时用户消息(interactMode=0)排在前面
|
||||||
const nextPageMessageGroups = res.item2.sort((a, b) => {
|
const nextPageMessageGroups = sortChatMessages(res.item2 || []);
|
||||||
const timeA = new Date(a.sendDate).getTime();
|
|
||||||
const timeB = new Date(b.sendDate).getTime();
|
|
||||||
|
|
||||||
// 如果时间相同,按interactMode排序(0排在前,1排在后)
|
this.$store.commit(
|
||||||
if (timeA === timeB) {
|
"prepend_AiMsgList",
|
||||||
return a.interactMode - b.interactMode;
|
nextPageMessageGroups
|
||||||
}
|
);
|
||||||
|
|
||||||
// 否则按时间升序排列
|
|
||||||
return timeA - timeB;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.messageGroups = [
|
|
||||||
...nextPageMessageGroups,
|
|
||||||
...this.messageGroups,
|
|
||||||
];
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
@ -1521,6 +1669,79 @@ export default {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message-transfer {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transfer-card {
|
||||||
|
width: 100%;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 40rpx 36rpx;
|
||||||
|
box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.transfer-card-title {
|
||||||
|
padding: 0 16rpx;
|
||||||
|
font-family: PingFang SC;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #333333;
|
||||||
|
line-height: 1.6;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transfer-card-options {
|
||||||
|
margin-top: 32rpx;
|
||||||
|
// padding: 24rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
// background-color: #f6f8ff;
|
||||||
|
display: flex;
|
||||||
|
gap: 36rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transfer-option {
|
||||||
|
flex: 1;
|
||||||
|
height: 112rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
background-color: #f6f8fa;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transfer-option.selected {
|
||||||
|
background-color: #eef0fe;
|
||||||
|
border-color: #dbe3ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transfer-option.disabled {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transfer-option-text {
|
||||||
|
font-family: PingFang SC;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transfer-option.selected .transfer-option-text {
|
||||||
|
color: #4a6cf7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transfer-card-status {
|
||||||
|
margin-top: 24rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-footer {
|
.chat-footer {
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@ 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_msgList: [],
|
vuex_msgList: [],
|
||||||
// 最近联系人/会话列表
|
// 最近联系人/会话列表
|
||||||
|
|
@ -179,6 +181,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) => {
|
||||||
|
|
|
||||||
|
|
@ -123,3 +123,67 @@ export function scrollToBottomByContentHeight(
|
||||||
.exec();
|
.exec();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理聊天消息内容:若内容为 JSON 字符串且符合预期结构,则提取并拼接为可读文本。
|
||||||
|
*
|
||||||
|
* 说明:
|
||||||
|
* - 首页对话存在部分消息内容为 JSON 字符串的情况(如包含 `answerTypeLabel/imageUrl/nearbyPaths`)
|
||||||
|
* - 这里做“尽量解析、解析失败回退原文”的处理,避免误伤普通文本消息
|
||||||
|
*
|
||||||
|
* @param {string} message - 原始消息文本
|
||||||
|
* @returns {string} - 处理后的文本
|
||||||
|
*/
|
||||||
|
export function processChatMessageContent(message) {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(message);
|
||||||
|
if (typeof parsed === "object" && parsed !== null) {
|
||||||
|
let content = "";
|
||||||
|
const { answerTypeLabel, imageUrl, nearbyPaths } = parsed;
|
||||||
|
|
||||||
|
if (answerTypeLabel) content += `${answerTypeLabel}\n`;
|
||||||
|
if (imageUrl) content += `${imageUrl}\n`;
|
||||||
|
if (nearbyPaths) content += `${nearbyPaths}\n`;
|
||||||
|
|
||||||
|
return content ? content.trim() : message;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 聊天消息排序:按 `sendDate` 升序;时间相同时,用户消息(`interactMode=0`)排在前面。
|
||||||
|
* 同时会对每条消息的 `message` 字段进行 `processChatMessageContent` 处理。
|
||||||
|
*
|
||||||
|
* @param {Array<any>} list - 会话详情接口返回的消息列表
|
||||||
|
* @returns {Array<any>} - 处理并排序后的新数组
|
||||||
|
*/
|
||||||
|
export function sortChatMessages(list = []) {
|
||||||
|
const processedList = (list || []).map((item) => ({
|
||||||
|
...item,
|
||||||
|
message: processChatMessageContent(item && item.message),
|
||||||
|
}));
|
||||||
|
|
||||||
|
return processedList.sort((a, b) => {
|
||||||
|
const timeA = new Date(a && a.sendDate).getTime();
|
||||||
|
const timeB = new Date(b && b.sendDate).getTime();
|
||||||
|
if (timeA === timeB) return (a && a.interactMode) - (b && b.interactMode);
|
||||||
|
return timeA - timeB;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 Date 格式化为 `HH:mm`。
|
||||||
|
*
|
||||||
|
* @param {Date} date - 时间对象
|
||||||
|
* @returns {string} - 格式化字符串
|
||||||
|
*/
|
||||||
|
export function formatHHmm(date) {
|
||||||
|
if (!(date instanceof Date) || Number.isNaN(date.getTime())) return "";
|
||||||
|
const hours = date.getHours().toString().padStart(2, "0");
|
||||||
|
const minutes = date.getMinutes().toString().padStart(2, "0");
|
||||||
|
return `${hours}:${minutes}`;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue