diff --git a/pages/chat/index.vue b/pages/chat/index.vue index 1a4ce7c..f2ed716 100644 --- a/pages/chat/index.vue +++ b/pages/chat/index.vue @@ -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) { return shouldShowTime(this.vuex_msgList, index); diff --git a/pages/home/index/index.vue b/pages/home/index/index.vue index 0556eab..f7f9ac0 100644 --- a/pages/home/index/index.vue +++ b/pages/home/index/index.vue @@ -285,6 +285,11 @@ import AdvicePhone from "@/components/AdvicePhone.vue"; import PerfectInfo from "@/components/PerfectInfo.vue"; import ChatHistory from "@/components/ChatHistory.vue"; // 导入新组件 import HeaderBar from "@/components/HeaderBar.vue"; // 导入头部组件 +import { + processChatMessageContent, + scrollToBottomByContentHeight, + sortChatMessages, +} from "@/utils/chat.js"; export default { components: { @@ -550,28 +555,9 @@ export default { // 新建对话时不执行滚动 if (this.isLoadingMore) return; - // 使用nextTick确保DOM已更新 - this.$nextTick(() => { - // setTimeout(() => { - 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); + scrollToBottomByContentHeight(this, { + selector: ".chat-content", + extraOffset: 200, }); }, 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) { // 关闭弹窗 @@ -859,52 +838,12 @@ export default { // 处理消息内容,如果是JSON格式则解析并格式化 processMessageContent(message) { - try { - // 尝试解析 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; + return processChatMessageContent(message); }, // 公共排序:按时间升序;时间相同,用户消息(interactMode=0)在前 sortMessages(list = []) { - const processedList = (list || []).map((item) => { - // 对每条消息进行处理 - 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; - }); + return sortChatMessages(list); }, // 刷新当前对话的消息详情 @@ -1020,18 +959,7 @@ export default { } // 将消息按sendDate升序排列,时间相同时用户消息(interactMode=0)排在前面 - const nextPageMessageGroups = res.item2.sort((a, b) => { - const timeA = new Date(a.sendDate).getTime(); - const timeB = new Date(b.sendDate).getTime(); - - // 如果时间相同,按interactMode排序(0排在前,1排在后) - if (timeA === timeB) { - return a.interactMode - b.interactMode; - } - - // 否则按时间升序排列 - return timeA - timeB; - }); + const nextPageMessageGroups = sortChatMessages(res.item2 || []); this.messageGroups = [ ...nextPageMessageGroups, diff --git a/utils/chat.js b/utils/chat.js index 714a464..38c146d 100644 --- a/utils/chat.js +++ b/utils/chat.js @@ -123,3 +123,67 @@ export function scrollToBottomByContentHeight( .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} list - 会话详情接口返回的消息列表 + * @returns {Array} - 处理并排序后的新数组 + */ +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}`; +}