-

{
- if (videoData.videoUrl) {
- window.open(videoData.videoUrl, "_blank");
- } else if (videoData.tencentUrl) {
- window.open(videoData.tencentUrl, "_blank");
- }
- }}
- />
-
-
+
);
}
- }
- } catch (e) {
- // JSON解析失败,按普通文本处理
- }
- // 普通文本消息
- return
{content}
;
+ try {
+ // 尝试解析JSON格式的视频数据
+ if (content.startsWith("{") && content.endsWith("}")) {
+ const videoData = JSON.parse(content);
+
+ // 验证必要的视频数据字段
+ if (
+ videoData &&
+ typeof videoData === "object" &&
+ videoData.previewImage &&
+ videoData.tencentUrl
+ ) {
+ const previewImageUrl = String(videoData.previewImage).replace(
+ /[`"']/g,
+ "",
+ );
+
+ // 创建点击处理函数
+ const handlePlayClick = (
+ e: React.MouseEvent,
+ msg: ChatRecord,
+ ) => {
+ e.stopPropagation();
+ // 如果没有视频URL且不在加载中,则发起下载请求
+ if (!videoData.videoUrl && !videoData.isLoading) {
+ handleVideoPlayRequest(videoData.tencentUrl, msg.id);
+ }
+ };
+
+ // 如果已有视频URL,显示视频播放器
+ if (videoData.videoUrl) {
+ return (
+
+ );
+ }
+
+ // 显示预览图,根据加载状态显示不同的图标
+ return (
+
+
+
handlePlayClick(e, msg)}
+ >
+

{
+ const target = e.target as HTMLImageElement;
+ const parent = target.parentElement?.parentElement;
+ if (parent) {
+ parent.innerHTML = `
[视频预览加载失败]
`;
+ }
+ }}
+ />
+
+ {videoData.isLoading ? (
+
+ ) : (
+
+ )}
+
+
+
+
+ );
+ }
+ }
+ return renderErrorMessage("[视频消息]");
+ } catch (e) {
+ console.warn("视频消息解析失败:", e);
+ return renderErrorMessage("[视频消息 - 解析失败]");
+ }
+
+ case 47: // 动图表情包(gif、其他表情包)
+ if (typeof content !== "string" || !content.trim()) {
+ return renderErrorMessage("[表情包 - 无效链接]");
+ }
+
+ // 使用工具函数判断表情包URL
+ if (isEmojiUrl(content)) {
+ return (
+
+

window.open(content, "_blank")}
+ onError={e => {
+ const target = e.target as HTMLImageElement;
+ const parent = target.parentElement;
+ if (parent) {
+ parent.innerHTML = `
[表情包加载失败]
`;
+ }
+ }}
+ />
+
+ );
+ }
+ return renderErrorMessage("[表情包]");
+
+ case 49: // 小程序/文章/其他:图文、文件
+ if (typeof content !== "string" || !content.trim()) {
+ return renderErrorMessage("[小程序/文章/文件消息 - 无效内容]");
+ }
+
+ try {
+ const trimmedContent = content.trim();
+
+ // 尝试解析JSON格式的消息
+ if (trimmedContent.startsWith("{") && trimmedContent.endsWith("}")) {
+ const messageData = JSON.parse(trimmedContent);
+
+ // 处理文章类型消息
+ if (
+ messageData.type === "link" &&
+ messageData.title &&
+ messageData.url
+ ) {
+ const { title, desc, thumbPath, url } = messageData;
+
+ return (
+
+
window.open(url, "_blank")}
+ >
+ {/* 标题在第一行 */}
+
{title}
+
+ {/* 下方:文字在左,图片在右 */}
+
+
+ {desc && (
+
+ {desc}
+
+ )}
+
+ {thumbPath && (
+
+

{
+ const target = e.target as HTMLImageElement;
+ target.style.display = "none";
+ }}
+ />
+
+ )}
+
+
+
文章
+
+ );
+ }
+
+ // 处理包含contentXml的小程序消息格式
+ if (messageData.contentXml && messageData.type === "miniprogram") {
+ const xmlContent = messageData.contentXml;
+
+ // 从XML中提取title
+ const titleMatch = xmlContent.match(/
([^<]*)<\/title>/);
+ const title = titleMatch ? titleMatch[1] : "小程序消息";
+
+ // 从XML中提取type字段
+ const typeMatch = xmlContent.match(
+ /[\s\S]*?(\d+)<\/type>[\s\S]*?<\/weappinfo>/,
+ );
+ const miniProgramType = typeMatch ? parseInt(typeMatch[1]) : 1;
+
+ // 从XML中提取thumburl或使用previewImage
+ const thumbUrlMatch = xmlContent.match(
+ /\s*([^<]*?)\s*<\/thumburl>/,
+ );
+ let thumbUrl = thumbUrlMatch ? thumbUrlMatch[1].trim() : "";
+
+ // 如果thumburl为空或无效,使用previewImage
+ if (!thumbUrl || thumbUrl === "`" || thumbUrl.includes("`")) {
+ thumbUrl = messageData.previewImage || "";
+ }
+
+ // 清理URL中的特殊字符
+ thumbUrl = thumbUrl.replace(/[`"']/g, "").replace(/&/g, "&");
+
+ // 从XML中提取appname或使用默认值
+ const appNameMatch =
+ xmlContent.match(/([^<]*)<\/appname>/) ||
+ xmlContent.match(
+ /([^<]*)<\/sourcedisplayname>/,
+ );
+ const appName = appNameMatch ? appNameMatch[1] : "小程序";
+
+ // 根据type类型渲染不同布局
+ if (miniProgramType === 2) {
+ // 类型2:图片区域布局(小程序昵称、图片、标题、小程序标识)
+ return (
+
+
+ {/* 小程序昵称 */}
+
{appName}
+ {/* 标题 */}
+
{title}
+ {/* 图片 */}
+ {thumbUrl && (
+
+

{
+ const target = e.target as HTMLImageElement;
+ target.style.display = "none";
+ }}
+ />
+
+ )}
+
+ {/* 小程序标识 */}
+
+ 小程序
+
+
+
+
+ );
+ } else {
+ // 默认类型:横向布局
+ return (
+
+
+ {thumbUrl && (
+

{
+ const target = e.target as HTMLImageElement;
+ target.style.display = "none";
+ }}
+ />
+ )}
+
+
+
{appName}
+
+ );
+ }
+ }
+
+ // 验证传统JSON格式的小程序数据结构
+ if (
+ messageData &&
+ typeof messageData === "object" &&
+ (messageData.title || messageData.appName)
+ ) {
+ return (
+
+
+ {messageData.thumb && (
+

{
+ const target = e.target as HTMLImageElement;
+ target.style.display = "none";
+ }}
+ />
+ )}
+
+
+ {messageData.title || "小程序消息"}
+
+ {messageData.appName && (
+
+ {messageData.appName}
+
+ )}
+
+
+
+ );
+ }
+ }
+
+ // 增强的文件消息处理
+ const isFileUrl =
+ content.startsWith("http") ||
+ content.startsWith("https") ||
+ content.startsWith("file://") ||
+ /\.(pdf|doc|docx|xls|xlsx|ppt|pptx|txt|zip|rar|7z)$/i.test(content);
+
+ if (isFileUrl) {
+ // 尝试从URL中提取文件名
+ const fileName = content.split("/").pop()?.split("?")[0] || "文件";
+ const fileExtension = fileName.split(".").pop()?.toLowerCase();
+
+ // 根据文件类型选择图标
+ let fileIcon = "📄";
+ if (fileExtension) {
+ const iconMap: { [key: string]: string } = {
+ pdf: "📕",
+ doc: "📘",
+ docx: "📘",
+ xls: "📗",
+ xlsx: "📗",
+ ppt: "📙",
+ pptx: "📙",
+ txt: "📝",
+ zip: "🗜️",
+ rar: "🗜️",
+ "7z": "🗜️",
+ jpg: "🖼️",
+ jpeg: "🖼️",
+ png: "🖼️",
+ gif: "🖼️",
+ mp4: "🎬",
+ avi: "🎬",
+ mov: "🎬",
+ mp3: "🎵",
+ wav: "🎵",
+ flac: "🎵",
+ };
+ fileIcon = iconMap[fileExtension] || "📄";
+ }
+
+ return (
+
+
+
{fileIcon}
+
+
+ {fileName.length > 20
+ ? fileName.substring(0, 20) + "..."
+ : fileName}
+
+
{
+ try {
+ window.open(content, "_blank");
+ } catch (e) {
+ console.error("文件打开失败:", e);
+ }
+ }}
+ >
+ 点击查看
+
+
+
+
+ );
+ }
+
+ return renderErrorMessage("[小程序/文件消息]");
+ } catch (e) {
+ console.warn("小程序/文件消息解析失败:", e);
+ return renderErrorMessage("[小程序/文件消息 - 解析失败]");
+ }
+
+ default: {
+ // 兼容旧版本和未知消息类型的处理逻辑
+ if (typeof content !== "string" || !content.trim()) {
+ return renderErrorMessage(
+ `[未知消息类型${msgType ? ` - ${msgType}` : ""}]`,
+ );
+ }
+
+ // 智能识别消息类型(兼容旧版本数据)
+ const contentStr = content.trim();
+
+ // 1. 检查是否为表情包(兼容旧逻辑)
+ const isLegacyEmoji =
+ contentStr.includes("ac-weremote-s2.oss-cn-shenzhen.aliyuncs.com") ||
+ /\.(gif|webp|png|jpg|jpeg)$/i.test(contentStr) ||
+ contentStr.includes("emoji") ||
+ contentStr.includes("sticker");
+
+ if (isLegacyEmoji) {
+ return (
+
+

window.open(contentStr, "_blank")}
+ onError={e => {
+ const target = e.target as HTMLImageElement;
+ const parent = target.parentElement;
+ if (parent) {
+ parent.innerHTML = `
[表情包加载失败]
`;
+ }
+ }}
+ />
+
+ );
+ }
+
+ // 2. 检查是否为JSON格式消息(包括视频、链接等)
+ if (contentStr.startsWith("{") && contentStr.endsWith("}")) {
+ try {
+ const jsonData = JSON.parse(contentStr);
+
+ // 检查是否为链接类型消息
+ if (jsonData.type === "link" && jsonData.title && jsonData.url) {
+ const { title, desc, thumbPath, url } = jsonData;
+
+ return (
+
+
window.open(url, "_blank")}
+ >
+ {thumbPath && (
+

{
+ const target = e.target as HTMLImageElement;
+ target.style.display = "none";
+ }}
+ />
+ )}
+
+
{title}
+ {desc && (
+
{desc}
+ )}
+
+
+
链接
+
+ );
+ }
+
+ // 检查是否为视频消息(兼容旧逻辑)
+ if (
+ jsonData &&
+ typeof jsonData === "object" &&
+ jsonData.previewImage &&
+ (jsonData.tencentUrl || jsonData.videoUrl)
+ ) {
+ const previewImageUrl = String(jsonData.previewImage).replace(
+ /[`"']/g,
+ "",
+ );
+ return (
+
+
+

{
+ const videoUrl =
+ jsonData.videoUrl || jsonData.tencentUrl;
+ if (videoUrl) {
+ window.open(videoUrl, "_blank");
+ }
+ }}
+ onError={e => {
+ const target = e.target as HTMLImageElement;
+ const parent = target.parentElement?.parentElement;
+ if (parent) {
+ parent.innerHTML = `
[视频预览加载失败]
`;
+ }
+ }}
+ />
+
+
+
+ );
+ }
+ } catch (e) {
+ console.warn("兼容模式JSON解析失败:", e);
+ }
+ }
+
+ // 3. 检查是否为图片链接
+ const isImageUrl =
+ contentStr.startsWith("http") &&
+ /\.(jpg|jpeg|png|gif|webp|bmp|svg)$/i.test(contentStr);
+
+ if (isImageUrl) {
+ return (
+
+

window.open(contentStr, "_blank")}
+ onError={e => {
+ const target = e.target as HTMLImageElement;
+ const parent = target.parentElement;
+ if (parent) {
+ parent.innerHTML = `
[图片加载失败]
`;
+ }
+ }}
+ />
+
+ );
+ }
+
+ // 4. 检查是否为文件链接
+ const isFileLink =
+ contentStr.startsWith("http") &&
+ /\.(pdf|doc|docx|xls|xlsx|ppt|pptx|txt|zip|rar|7z)$/i.test(
+ contentStr,
+ );
+
+ if (isFileLink) {
+ const fileName = contentStr.split("/").pop()?.split("?")[0] || "文件";
+ return (
+
+
+
📄
+
+
+ {fileName.length > 20
+ ? fileName.substring(0, 20) + "..."
+ : fileName}
+
+
window.open(contentStr, "_blank")}
+ >
+ 点击查看
+
+
+
+
+ );
+ }
+
+ // 5. 默认按文本消息处理
+ return {content}
;
+ }
+ }
};
// 获取群成员头像
@@ -152,13 +851,13 @@ const MessageRecord: React.FC = ({ contract }) => {
className={styles.messageAvatar}
/>
-
+
{!isOwn && (
{contract.nickname}
)}
- {parseMessageContent(msg?.content)}
+ <>{parseMessageContent(msg?.content, msg, msg?.msgType)}>
>
)}
@@ -172,24 +871,24 @@ const MessageRecord: React.FC
= ({ contract }) => {
className={styles.messageAvatar}
/>
-
+
{!isOwn && (
{msg?.sender?.nickname}
)}
- {parseMessageContent(
- clearWechatidInContent(msg?.sender, msg?.content),
- )}
+ <>
+ {parseMessageContent(
+ clearWechatidInContent(msg?.sender, msg?.content),
+ msg,
+ msg?.msgType,
+ )}
+ >
>
)}
- {isOwn && (
-
- {parseMessageContent(msg?.content)}
-
- )}
+ {isOwn && <>{parseMessageContent(msg?.content, msg, msg?.msgType)}>}
);
diff --git a/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/demo.tsx b/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/demo.tsx
new file mode 100644
index 00000000..e1bfb7ca
--- /dev/null
+++ b/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/demo.tsx
@@ -0,0 +1,669 @@
+import React, { useEffect, useRef } from "react";
+import { Layout, Button, Avatar, Space, Dropdown, Menu, Tooltip } from "antd";
+import {
+ PhoneOutlined,
+ VideoCameraOutlined,
+ MoreOutlined,
+ UserOutlined,
+ DownloadOutlined,
+ FileOutlined,
+ FilePdfOutlined,
+ FileWordOutlined,
+ FileExcelOutlined,
+ FilePptOutlined,
+ PlayCircleFilled,
+ TeamOutlined,
+ FolderOutlined,
+ EnvironmentOutlined,
+} from "@ant-design/icons";
+import { ChatRecord, ContractData, weChatGroup } from "@/pages/pc/ckbox/data";
+import styles from "./ChatWindow.module.scss";
+import { useWebSocketStore } from "@/store/module/websocket/websocket";
+import { formatWechatTime } from "@/utils/common";
+import ProfileCard from "./components/ProfileCard";
+import MessageEnter from "./components/MessageEnter";
+import { useWeChatStore } from "@/store/module/weChat/weChat";
+const { Header, Content } = Layout;
+
+interface ChatWindowProps {
+ contract: ContractData | weChatGroup;
+ showProfile?: boolean;
+ onToggleProfile?: () => void;
+}
+
+const ChatWindow: React.FC = ({
+ contract,
+ showProfile = true,
+ onToggleProfile,
+}) => {
+ const messagesEndRef = useRef(null);
+ const currentMessages = useWeChatStore(state => state.currentMessages);
+ const prevMessagesRef = useRef(currentMessages);
+
+ useEffect(() => {
+ const prevMessages = prevMessagesRef.current;
+
+ const hasVideoStateChange = currentMessages.some((msg, index) => {
+ // 首先检查消息对象本身是否为null或undefined
+ if (!msg || !msg.content) return false;
+
+ const prevMsg = prevMessages[index];
+ if (!prevMsg || !prevMsg.content || prevMsg.id !== msg.id) return false;
+
+ try {
+ const currentContent =
+ typeof msg.content === "string"
+ ? JSON.parse(msg.content)
+ : msg.content;
+ const prevContent =
+ typeof prevMsg.content === "string"
+ ? JSON.parse(prevMsg.content)
+ : prevMsg.content;
+
+ // 检查视频状态是否发生变化(开始加载、完成加载、获得URL)
+ const currentHasVideo =
+ currentContent.previewImage && currentContent.tencentUrl;
+ const prevHasVideo = prevContent.previewImage && prevContent.tencentUrl;
+
+ if (currentHasVideo && prevHasVideo) {
+ // 检查加载状态变化或视频URL变化
+ return (
+ currentContent.isLoading !== prevContent.isLoading ||
+ currentContent.videoUrl !== prevContent.videoUrl
+ );
+ }
+
+ return false;
+ } catch (e) {
+ return false;
+ }
+ });
+
+ // 只有在没有视频状态变化时才自动滚动到底部
+ if (!hasVideoStateChange) {
+ scrollToBottom();
+ }
+
+ // 更新上一次的消息状态
+ prevMessagesRef.current = currentMessages;
+ }, [currentMessages]);
+
+ const scrollToBottom = () => {
+ messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
+ };
+
+ // 处理视频播放请求,发送socket请求获取真实视频地址
+ const handleVideoPlayRequest = (tencentUrl: string, messageId: number) => {
+ console.log("发送视频下载请求:", { messageId, tencentUrl });
+
+ // 先设置加载状态
+ useWeChatStore.getState().setVideoLoading(messageId, true);
+
+ // 构建socket请求数据
+ useWebSocketStore.getState().sendCommand("CmdDownloadVideo", {
+ chatroomMessageId: contract.chatroomId ? messageId : 0,
+ friendMessageId: contract.chatroomId ? 0 : messageId,
+ seq: `${+new Date()}`, // 使用时间戳作为请求序列号
+ tencentUrl: tencentUrl,
+ wechatAccountId: contract.wechatAccountId,
+ });
+ };
+
+ // 解析消息内容,判断消息类型并返回对应的渲染内容
+ const parseMessageContent = (
+ content: string | null | undefined,
+ msg: ChatRecord,
+ ) => {
+ // 处理null或undefined的内容
+ if (content === null || content === undefined) {
+ return 消息内容不可用
;
+ }
+ // 检查是否为表情包
+ if (
+ typeof content === "string" &&
+ content.includes("ac-weremote-s2.oss-cn-shenzhen.aliyuncs.com") &&
+ content.includes("#")
+ ) {
+ return (
+
+

window.open(content, "_blank")}
+ />
+
+ );
+ }
+
+ // 检查是否为带预览图的视频消息
+ try {
+ if (
+ typeof content === "string" &&
+ content.trim().startsWith("{") &&
+ content.trim().endsWith("}")
+ ) {
+ const videoData = JSON.parse(content);
+ // 处理视频消息格式 {"previewImage":"https://...", "tencentUrl":"...", "videoUrl":"...", "isLoading":true}
+ if (videoData.previewImage && videoData.tencentUrl) {
+ // 提取预览图URL,去掉可能的引号
+ const previewImageUrl = videoData.previewImage.replace(/[`"']/g, "");
+
+ // 创建点击处理函数
+ const handlePlayClick = (e: React.MouseEvent) => {
+ e.stopPropagation();
+ // 如果没有视频URL且不在加载中,则发起下载请求
+ if (!videoData.videoUrl && !videoData.isLoading) {
+ handleVideoPlayRequest(videoData.tencentUrl, msg.id);
+ }
+ };
+
+ // 如果已有视频URL,显示视频播放器
+ if (videoData.videoUrl) {
+ return (
+
+ );
+ }
+
+ // 显示预览图,根据加载状态显示不同的图标
+ return (
+
+
+

+
+ {videoData.isLoading ? (
+
+ ) : (
+
+ )}
+
+
+
+ );
+ }
+ // 保留原有的视频处理逻辑
+ else if (
+ videoData.type === "video" &&
+ videoData.url &&
+ videoData.thumb
+ ) {
+ return (
+
+ );
+ }
+ }
+ } catch (e) {
+ // 解析JSON失败,不是视频消息
+ console.log("解析视频消息失败:", e);
+ }
+
+ // 检查是否为图片链接
+ if (
+ typeof content === "string" &&
+ (content.match(/\.(jpg|jpeg|png|gif)$/i) ||
+ (content.includes("oss-cn-shenzhen.aliyuncs.com") &&
+ content.includes(".jpg")))
+ ) {
+ return (
+
+

window.open(content, "_blank")}
+ />
+
+ );
+ }
+
+ // 检查是否为视频链接
+ if (
+ typeof content === "string" &&
+ (content.match(/\.(mp4|avi|mov|wmv|flv)$/i) ||
+ (content.includes("oss-cn-shenzhen.aliyuncs.com") &&
+ content.includes(".mp4")))
+ ) {
+ return (
+
+ );
+ }
+
+ // 检查是否为音频链接
+ if (
+ typeof content === "string" &&
+ (content.match(/\.(mp3|wav|ogg|m4a)$/i) ||
+ (content.includes("oss-cn-shenzhen.aliyuncs.com") &&
+ content.includes(".mp3")))
+ ) {
+ return (
+
+ );
+ }
+
+ // 检查是否为Office文件链接
+ if (
+ typeof content === "string" &&
+ content.match(/\.(doc|docx|xls|xlsx|ppt|pptx|pdf)$/i)
+ ) {
+ const fileName = content.split("/").pop() || "文件";
+ const fileExt = fileName.split(".").pop()?.toLowerCase();
+
+ // 根据文件类型选择不同的图标
+ let fileIcon = (
+
+ );
+
+ if (fileExt === "pdf") {
+ fileIcon = (
+
+ );
+ } else if (fileExt === "doc" || fileExt === "docx") {
+ fileIcon = (
+
+ );
+ } else if (fileExt === "xls" || fileExt === "xlsx") {
+ fileIcon = (
+
+ );
+ } else if (fileExt === "ppt" || fileExt === "pptx") {
+ fileIcon = (
+
+ );
+ }
+
+ return (
+
+ );
+ }
+
+ // 检查是否为文件消息(JSON格式)
+ try {
+ if (
+ typeof content === "string" &&
+ content.trim().startsWith("{") &&
+ content.trim().endsWith("}")
+ ) {
+ const fileData = JSON.parse(content);
+ if (fileData.type === "file" && fileData.title) {
+ // 检查是否为Office文件
+ const fileExt = fileData.title.split(".").pop()?.toLowerCase();
+ let fileIcon = (
+
+ );
+
+ if (fileExt === "pdf") {
+ fileIcon = (
+
+ );
+ } else if (fileExt === "doc" || fileExt === "docx") {
+ fileIcon = (
+
+ );
+ } else if (fileExt === "xls" || fileExt === "xlsx") {
+ fileIcon = (
+
+ );
+ } else if (fileExt === "ppt" || fileExt === "pptx") {
+ fileIcon = (
+
+ );
+ }
+
+ return (
+
+ );
+ }
+ }
+ } catch (e) {
+ // 解析JSON失败,不是文件消息
+ }
+
+ // 检查是否为位置信息
+ if (
+ typeof content === "string" &&
+ (content.includes("
+
+
+
{label}
+ {coordinates && (
+
+ {coordinates}
+
+ )}
+
+
+ );
+ }
+
+ // 默认为文本消息
+ return
{content}
;
+ };
+
+ // 用于分组消息并添加时间戳的辅助函数
+ const groupMessagesByTime = (messages: ChatRecord[]) => {
+ return messages
+ .filter(msg => msg !== null && msg !== undefined) // 过滤掉null和undefined的消息
+ .map(msg => ({
+ time: formatWechatTime(msg?.wechatTime),
+ messages: [msg],
+ }));
+ };
+
+ const renderMessage = (msg: ChatRecord) => {
+ // 添加null检查,防止访问null对象的属性
+ if (!msg) return null;
+
+ const isOwn = msg?.isSend;
+ return (
+
+
+ {!isOwn && (
+
}
+ className={styles.messageAvatar}
+ />
+ )}
+
+ {!isOwn && (
+
{msg?.senderName}
+ )}
+ {parseMessageContent(msg?.content, msg)}
+
+
+
+ );
+ };
+
+ const chatMenu = (
+
+ );
+
+ return (
+
+ {/* 聊天主体区域 */}
+
+ {/* 聊天头部 */}
+
+
+
:
+ }
+ />
+
+
+ {contract.nickname || contract.name}
+
+
+
+
+
+ }
+ className={styles.headerButton}
+ />
+
+
+ }
+ className={styles.headerButton}
+ />
+
+
+ }
+ className={styles.headerButton}
+ />
+
+
+
+
+ {/* 聊天内容 */}
+
+
+ {groupMessagesByTime(currentMessages).map((group, groupIndex) => (
+
+ {group.time}
+ {group.messages.map(renderMessage)}
+
+ ))}
+
+
+
+
+ {/* 消息输入组件 */}
+
+
+
+ {/* 右侧个人资料卡片 */}
+
+
+ );
+};
+
+export default ChatWindow;
diff --git a/Cunkebao/src/router/module/workspace.tsx b/Cunkebao/src/router/module/workspace.tsx
index 5c010122..79878bf3 100644
--- a/Cunkebao/src/router/module/workspace.tsx
+++ b/Cunkebao/src/router/module/workspace.tsx
@@ -8,9 +8,9 @@ import AutoGroupForm from "@/pages/mobile/workspace/auto-group/form";
import GroupPush from "@/pages/mobile/workspace/group-push/list";
import FormGroupPush from "@/pages/mobile/workspace/group-push/form";
import DetailGroupPush from "@/pages/mobile/workspace/group-push/detail";
-import MomentsSync from "@/pages/mobile/workspace/moments-sync/MomentsSync";
-import MomentsSyncDetail from "@/pages/mobile/workspace/moments-sync/Detail";
+import MomentsSync from "@/pages/mobile/workspace/moments-sync/list";
import NewMomentsSync from "@/pages/mobile/workspace/moments-sync/new/index";
+import MomentsSyncRecord from "@/pages/mobile/workspace/moments-sync/record";
import AIAssistant from "@/pages/mobile/workspace/ai-assistant/AIAssistant";
import TrafficDistribution from "@/pages/mobile/workspace/traffic-distribution/list/index";
import TrafficDistributionDetail from "@/pages/mobile/workspace/traffic-distribution/detail/index";
@@ -98,9 +98,10 @@ const workspaceRoutes = [
element:
,
auth: true,
},
+
{
- path: "/workspace/moments-sync/:id",
- element:
,
+ path: "/workspace/moments-sync/record/:id",
+ element:
,
auth: true,
},
{