refactor(chat): 将消息处理和格式化功能提取到工具类中

This commit is contained in:
yangzhe 2025-12-18 08:54:54 +08:00
parent 9e10f6788d
commit 5780461fa4
3 changed files with 75 additions and 90 deletions

View File

@ -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);

View File

@ -285,6 +285,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: {
@ -550,28 +555,9 @@ export default {
// //
if (this.isLoadingMore) return; if (this.isLoadingMore) return;
// 使nextTickDOM 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);
// scrollTopscrollToView
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) {
@ -825,13 +811,6 @@ export default {
}); });
}, },
//
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) {
// //
@ -859,52 +838,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;
});
}, },
// //
@ -1020,18 +959,7 @@ 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();
// interactMode01
if (timeA === timeB) {
return a.interactMode - b.interactMode;
}
//
return timeA - timeB;
});
this.messageGroups = [ this.messageGroups = [
...nextPageMessageGroups, ...nextPageMessageGroups,

View File

@ -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}`;
}