loadMoreMessages()}>
@@ -604,10 +754,24 @@ const MessageRecord: React.FC
= ({ contract }) => {
{group.time}
{group.messages
.filter(v => ![10000].includes(v.msgType))
- .map(renderMessage)}
+ .map(msg => {
+ return renderMessage(msg);
+ })}
))}
+ {/* 右键菜单组件 */}
+
+ {/* 转发模态框 */}
+
);
};
diff --git a/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/api.ts b/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/api.ts
new file mode 100644
index 00000000..d801999e
--- /dev/null
+++ b/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/api.ts
@@ -0,0 +1,106 @@
+// 朋友圈相关的API接口
+import { useWebSocketStore } from "@/store/module/websocket/websocket";
+
+// 朋友圈请求参数接口
+export interface FetchMomentParams {
+ wechatAccountId: number;
+ wechatFriendId?: number;
+ createTimeSec?: number;
+ prevSnsId?: number;
+ count?: number;
+ isTimeline?: boolean;
+ seq?: number;
+}
+
+// 获取朋友圈数据
+export const fetchFriendsCircleData = async (params: FetchMomentParams) => {
+ const { sendCommand } = useWebSocketStore.getState();
+ sendCommand("CmdFetchMoment", params);
+};
+
+// 点赞朋友圈
+export const likeMoment = async (params: {
+ wechatAccountId: number;
+ wechatFriendId?: number;
+ snsId: string;
+ seq?: number;
+}) => {
+ const { sendCommand } = useWebSocketStore.getState();
+ const requestData = {
+ cmdType: "CmdMomentInteract",
+ momentInteractType: 1,
+ wechatAccountId: params.wechatAccountId,
+ wechatFriendId: params.wechatFriendId || 0,
+ snsId: params.snsId,
+ seq: params.seq || Date.now(),
+ };
+
+ sendCommand("CmdMomentInteract", requestData);
+};
+
+// 取消点赞
+export const cancelLikeMoment = async (params: {
+ wechatAccountId: number;
+ wechatFriendId?: number;
+ snsId: string;
+ seq?: number;
+}) => {
+ const { sendCommand } = useWebSocketStore.getState();
+ const requestData = {
+ cmdType: "CmdMomentCancelInteract",
+ optType: 1,
+ wechatAccountId: params.wechatAccountId,
+ wechatFriendId: params.wechatFriendId || 0,
+ CommentId2: "",
+ CommentTime: 0,
+ snsId: params.snsId,
+ seq: params.seq || Date.now(),
+ };
+
+ sendCommand("CmdMomentCancelInteract", requestData);
+};
+
+// 评论朋友圈
+export const commentMoment = async (params: {
+ wechatAccountId: number;
+ wechatFriendId?: number;
+ snsId: string;
+ sendWord: string;
+ seq?: number;
+}) => {
+ const { sendCommand } = useWebSocketStore.getState();
+ const requestData = {
+ cmdType: "CmdMomentInteract",
+ wechatAccountId: params.wechatAccountId,
+ wechatFriendId: params.wechatFriendId || 0,
+ snsId: params.snsId,
+ sendWord: params.sendWord,
+ momentInteractType: 2,
+ seq: params.seq || Date.now(),
+ };
+
+ sendCommand("CmdMomentInteract", requestData);
+};
+
+// 撤销评论
+export const cancelCommentMoment = async (params: {
+ wechatAccountId: number;
+ wechatFriendId?: number;
+ snsId: string;
+ CommentTime: number;
+ seq?: number;
+}) => {
+ const { sendCommand } = useWebSocketStore.getState();
+ const requestData = {
+ cmdType: "CmdMomentCancelInteract",
+ optType: 2,
+ wechatAccountId: params.wechatAccountId,
+ wechatFriendId: params.wechatFriendId || 0,
+ CommentId2: "",
+ CommentTime: params.CommentTime,
+ snsId: params.snsId,
+ seq: params.seq || Date.now(),
+ };
+
+ sendCommand("CmdMomentCancelInteract", requestData);
+};
diff --git a/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/components/api.ts b/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/components/api.ts
new file mode 100644
index 00000000..311b5100
--- /dev/null
+++ b/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/components/api.ts
@@ -0,0 +1,107 @@
+// 朋友圈相关的API接口
+import { useWebSocketStore } from "@/store/module/websocket/websocket";
+
+// 朋友圈请求参数接口
+export interface FetchMomentParams {
+ wechatAccountId: number;
+ wechatFriendId?: number;
+ createTimeSec?: number;
+ prevSnsId?: number;
+ count?: number;
+ isTimeline?: boolean;
+ seq?: number;
+}
+
+// 获取朋友圈数据
+export const fetchFriendsCircleData = async (params: FetchMomentParams) => {
+ const { sendCommand } = useWebSocketStore.getState();
+ sendCommand("CmdFetchMoment", params);
+};
+
+// 点赞朋友圈
+export const likeMoment = async (params: {
+ wechatAccountId: number;
+ wechatFriendId?: number;
+ snsId: string;
+ seq?: number;
+}) => {
+ const { sendCommand } = useWebSocketStore.getState();
+ const requestData = {
+ cmdType: "CmdMomentInteract",
+ momentInteractType: 1,
+ wechatAccountId: params.wechatAccountId,
+ wechatFriendId: params.wechatFriendId || 0,
+ snsId: params.snsId,
+ seq: params.seq || Date.now(),
+ };
+
+ sendCommand("CmdMomentInteract", requestData);
+};
+
+// 取消点赞
+export const cancelLikeMoment = async (params: {
+ wechatAccountId: number;
+ wechatFriendId?: number;
+ snsId: string;
+ seq?: number;
+}) => {
+ const { sendCommand } = useWebSocketStore.getState();
+ const requestData = {
+ cmdType: "CmdMomentCancelInteract",
+ optType: 1,
+ wechatAccountId: params.wechatAccountId,
+ wechatFriendId: params.wechatFriendId || 0,
+ CommentId2: "",
+ CommentTime: 0,
+ snsId: params.snsId,
+ seq: params.seq || Date.now(),
+ };
+
+ sendCommand("CmdMomentCancelInteract", requestData);
+};
+
+// 评论朋友圈
+export const commentMoment = async (params: {
+ wechatAccountId: number;
+ wechatFriendId?: number;
+ snsId: string;
+ sendWord: string;
+ seq?: number;
+}) => {
+ const { sendCommand } = useWebSocketStore.getState();
+ const requestData = {
+ cmdType: "CmdMomentInteract",
+ wechatAccountId: params.wechatAccountId,
+ wechatFriendId: params.wechatFriendId || 0,
+ snsId: params.snsId,
+ sendWord: params.sendWord,
+ momentInteractType: 2,
+ seq: params.seq || Date.now(),
+ };
+
+ sendCommand("CmdMomentInteract", requestData);
+};
+
+// 撤销评论
+export const cancelCommentMoment = async (params: {
+ wechatAccountId: number;
+ wechatFriendId?: number;
+ snsId: string;
+ commentTime: number;
+ commentId2: number;
+ seq?: number;
+}) => {
+ const { sendCommand } = useWebSocketStore.getState();
+ const requestData = {
+ cmdType: "CmdMomentCancelInteract",
+ optType: 2,
+ wechatAccountId: params.wechatAccountId,
+ wechatFriendId: params.wechatFriendId || 0,
+ CommentId2: params.commentId2,
+ CommentTime: params.commentTime,
+ snsId: params.snsId,
+ seq: params.seq || Date.now(),
+ };
+
+ sendCommand("CmdMomentCancelInteract", requestData);
+};
diff --git a/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/components/friendCard.tsx b/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/components/friendCard.tsx
new file mode 100644
index 00000000..ada75633
--- /dev/null
+++ b/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/components/friendCard.tsx
@@ -0,0 +1,320 @@
+import React, { useState } from "react";
+import { Avatar, Button, Image, Spin, Input, message } from "antd";
+import {
+ HeartOutlined,
+ MessageOutlined,
+ LoadingOutlined,
+ SendOutlined,
+ DeleteOutlined,
+} from "@ant-design/icons";
+import {
+ CommentItem,
+ likeListItem,
+ FriendCardProps,
+ MomentListProps,
+ FriendsCircleItem,
+} from "@/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.data";
+import styles from "../index.module.scss";
+import {
+ likeMoment,
+ cancelLikeMoment,
+ commentMoment,
+ cancelCommentMoment,
+} from "./api";
+import { comfirm } from "@/utils/common";
+
+import { useWeChatStore } from "@/store/module/weChat/weChat";
+// 单个朋友圈项目组件
+export const FriendCard: React.FC
= ({
+ monent,
+ isNotMy = false,
+ currentKf,
+ wechatFriendId,
+ formatTime,
+}) => {
+ const content = monent?.momentEntity?.content || "";
+ const images = monent?.momentEntity?.resUrls || [];
+ const time = formatTime(monent.createTime);
+ const likesCount = monent?.likeList?.length || 0;
+ const commentsCount = monent?.commentList?.length || 0;
+ const { updateLikeMoment, updateComment } = useWeChatStore();
+
+ // 评论相关状态
+ const [showCommentInput, setShowCommentInput] = useState(false);
+ const [commentText, setCommentText] = useState("");
+
+ const handleLike = (moment: FriendsCircleItem) => {
+ console.log(currentKf);
+
+ //判断是否已经点赞了
+ const isLiked = moment?.likeList?.some(
+ (item: likeListItem) => item.wechatId === currentKf?.wechatId,
+ );
+ if (isLiked) {
+ cancelLikeMoment({
+ wechatAccountId: currentKf?.id || 0,
+ wechatFriendId: wechatFriendId || 0,
+ snsId: moment.snsId,
+ seq: Date.now(),
+ });
+ // 更新点赞
+ updateLikeMoment(
+ moment.snsId,
+ moment.likeList.filter(v => v.wechatId !== currentKf?.wechatId),
+ );
+ } else {
+ likeMoment({
+ wechatAccountId: currentKf?.id || 0,
+ wechatFriendId: wechatFriendId || 0,
+ snsId: moment.snsId,
+ seq: Date.now(),
+ });
+ // 更新点赞
+ updateLikeMoment(moment.snsId, [
+ ...moment.likeList,
+ {
+ createTime: Date.now(),
+ nickName: currentKf?.nickname || "",
+ wechatId: currentKf?.wechatId || "",
+ },
+ ]);
+ }
+ };
+
+ const handleSendComment = monent => {
+ if (!commentText.trim()) {
+ message.warning("请输入评论内容");
+ return;
+ }
+
+ // TODO: 调用发送评论的API
+ commentMoment({
+ wechatAccountId: currentKf?.id || 0,
+ wechatFriendId: wechatFriendId || 0,
+ snsId: monent.snsId,
+ sendWord: commentText,
+ seq: Date.now(),
+ });
+ // 更新评论
+ updateComment(monent.snsId, [
+ ...monent.commentList,
+ {
+ commentArg: 0,
+ commentId1: Date.now(),
+ commentId2: Date.now(),
+ commentTime: Date.now(),
+ content: commentText,
+ nickName: currentKf?.nickname || "",
+ wechatId: currentKf?.wechatId || "",
+ },
+ ]);
+ // 清空输入框并隐藏
+ setCommentText("");
+ setShowCommentInput(false);
+ message.success("评论发送成功");
+ };
+
+ const handleDeleteComment = (snsId: string, comment: CommentItem) => {
+ // TODO: 调用删除评论的API
+ comfirm("确定删除评论吗?").then(() => {
+ cancelCommentMoment({
+ wechatAccountId: currentKf?.id || 0,
+ wechatFriendId: wechatFriendId || 0,
+ snsId: snsId,
+ seq: Date.now(),
+ commentId2: comment.commentId2,
+ commentTime: comment.commentTime,
+ });
+ // 更新评论
+ const commentList = monent.commentList.filter(v => {
+ return !(
+ v.commentId2 == comment.commentId2 &&
+ v.wechatId == currentKf?.wechatId
+ );
+ });
+ updateComment(snsId, commentList);
+ message.success("评论删除成功");
+ });
+ };
+
+ return (
+
+ {isNotMy && (
+
+ )}
+
+
+
+
+
{content}
+ {images && images.length > 0 && (
+
+ {images.map((image, index) => (
+
+ ))}
+
+ )}
+
+
+
+
{time}
+
+ }
+ onClick={() => handleLike(monent)}
+ className={styles.actionButton}
+ >
+ {likesCount > 0 && {likesCount}}
+
+ }
+ onClick={() => setShowCommentInput(!showCommentInput)}
+ className={styles.actionButton}
+ >
+ {commentsCount > 0 && {commentsCount}}
+
+
+
+
+ {/* 点赞和评论区域 */}
+ {(monent?.likeList?.length > 0 || monent?.commentList?.length > 0) && (
+
+ {/* 点赞列表 */}
+ {monent?.likeList?.length > 0 && (
+
+
+
+ {monent?.likeList?.map((like, index) => (
+
+ {like.nickName}
+ {index < (monent?.likeList?.length || 0) - 1 && "、"}
+
+ ))}
+
+
+ )}
+
+ {/* 评论列表 */}
+ {monent?.commentList?.length > 0 && (
+
+ {monent?.commentList?.map(comment => (
+
+
+ {comment.nickName}
+
+ :
+
+ {comment.content}
+
+ }
+ onClick={() => handleDeleteComment(monent.snsId, comment)}
+ className={styles.deleteCommentBtn}
+ danger
+ />
+
+ ))}
+
+ )}
+
+ )}
+
+ {/* 评论输入框 */}
+ {showCommentInput && (
+
+
setCommentText(e.target.value)}
+ placeholder="写评论..."
+ autoSize={{ minRows: 2, maxRows: 4 }}
+ className={styles.commentInput}
+ />
+
+ }
+ onClick={() => handleSendComment(monent)}
+ className={styles.sendCommentBtn}
+ >
+ 发送
+
+
+
+ )}
+
+
+ );
+};
+
+// 朋友圈列表组件
+export const MomentList: React.FC = ({
+ MomentCommon,
+ MomentCommonLoading,
+ formatTime,
+ currentKf,
+ loadMomentData,
+}) => {
+ return (
+
+ {MomentCommon.length > 0 ? (
+ <>
+ {MomentCommon.map((v, index) => (
+
+
+
+ ))}
+ {MomentCommonLoading && (
+
+ } /> 加载中...
+
+ )}
+ {!MomentCommonLoading && (
+
+
+
+ )}
+ >
+ ) : MomentCommonLoading ? (
+
+ } /> 加载中...
+
+ ) : (
+
暂无我的朋友圈内容
+ )}
+
+ );
+};
diff --git a/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.data.ts b/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.data.ts
new file mode 100644
index 00000000..d61c2870
--- /dev/null
+++ b/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.data.ts
@@ -0,0 +1,71 @@
+// 评论数据类型
+export interface CommentItem {
+ commentArg: number;
+ commentId1: number;
+ commentId2: number;
+ commentTime: number;
+ content: string;
+ nickName: string;
+ wechatId: string;
+}
+
+// 点赞数据类型
+export interface LikeItem {
+ createTime: number;
+ nickName: string;
+ wechatId: string;
+}
+
+// 朋友圈实体数据类型
+export interface MomentEntity {
+ content: string;
+ createTime: number;
+ lat: number;
+ lng: number;
+ location: string;
+ objectType: number;
+ picSize: number;
+ resUrls: string[];
+ snsId: string;
+ urls: string[];
+ userName: string;
+}
+
+// 朋友圈数据类型定义
+export interface FriendsCircleItem {
+ commentList: CommentItem[];
+ createTime: number;
+ likeList: LikeItem[];
+ momentEntity: MomentEntity;
+ snsId: string;
+ type: number;
+}
+
+// API响应类型
+export interface ApiResponse {
+ list: FriendsCircleItem[];
+ total: number;
+ hasMore: boolean;
+}
+
+export interface FriendCardProps {
+ monent: FriendsCircleItem;
+ isNotMy?: boolean;
+ currentKf?: any;
+ wechatFriendId?: number;
+ formatTime: (time: number) => string;
+}
+
+export interface MomentListProps {
+ MomentCommon: FriendsCircleItem[];
+ MomentCommonLoading: boolean;
+ currentKf?: any;
+ wechatFriendId?: number;
+ formatTime: (time: number) => string;
+ loadMomentData: (loadMore: boolean) => void;
+}
+export interface likeListItem {
+ createTime: number;
+ nickName: string;
+ wechatId: string;
+}
diff --git a/Cunkebao/src/store/module/websocket/sendMessages.ts b/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.func.ts
similarity index 100%
rename from Cunkebao/src/store/module/websocket/sendMessages.ts
rename to Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.func.ts
diff --git a/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.module.scss b/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.module.scss
new file mode 100644
index 00000000..1c39f04c
--- /dev/null
+++ b/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.module.scss
@@ -0,0 +1,450 @@
+/* ===== 组件根容器 ===== */
+.friendsCircle {
+ height: 100%;
+ overflow-y: auto;
+ padding: 0;
+ background-color: #f5f5f5;
+
+ /* 滚动条样式 */
+ &::-webkit-scrollbar {
+ width: 6px;
+ }
+
+ &::-webkit-scrollbar-track {
+ background: #f1f1f1;
+ border-radius: 3px;
+ }
+
+ &::-webkit-scrollbar-thumb {
+ background: #c1c1c1;
+ border-radius: 3px;
+
+ &:hover {
+ background: #a8a8a8;
+ }
+ }
+
+ /* ===== 折叠面板样式 ===== */
+ .collapseContainer {
+ margin-bottom: 1px;
+
+ :global(.ant-collapse-item) {
+ border-bottom: 1px solid #e8e8e8;
+
+ &:last-child {
+ border-bottom: 1px solid #e8e8e8;
+ }
+ }
+
+ :global(.ant-collapse-header) {
+ padding: 12px 16px !important;
+ background-color: #ffffff;
+
+ &:hover {
+ background-color: #f8f8f8;
+ }
+ }
+
+ :global(.ant-collapse-content-box) {
+ padding: 16px;
+ background-color: #ffffff;
+ }
+
+ /* 折叠面板头部 */
+ .collapseHeader {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ .avatar {
+ width: 20px;
+ height: 20px;
+ border-radius: 5px;
+ }
+ /* 特殊头像样式 */
+ .specialAvatar {
+ background-color: #1890ff;
+ }
+
+ /* 群组头像样式 */
+ .groupAvatars {
+ display: flex;
+ position: relative;
+ width: 32px;
+ height: 32px;
+
+ .groupAvatar {
+ position: absolute;
+ border: 1px solid #fff;
+ background-color: #52c41a;
+
+ &:nth-child(1) {
+ top: 0;
+ left: 0;
+ z-index: 4;
+ }
+
+ &:nth-child(2) {
+ top: 0;
+ right: 0;
+ z-index: 3;
+ }
+
+ &:nth-child(3) {
+ bottom: 0;
+ left: 0;
+ z-index: 2;
+ }
+
+ &:nth-child(4) {
+ bottom: 0;
+ right: 0;
+ z-index: 1;
+ }
+ }
+ }
+
+ /* 特殊文本样式 */
+ .specialText {
+ font-size: 16px;
+ color: #333;
+ font-weight: 400;
+ }
+ }
+ }
+
+ /* ===== 内容区域样式 ===== */
+ .myCircleContent,
+ .squareContent {
+ padding: 0;
+
+ /* 项目包装器 */
+ .itemWrapper {
+ margin-bottom: 1px;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+
+ /* ===== 朋友圈项目样式 ===== */
+ .circleItem {
+ background-color: #ffffff;
+ margin-bottom: 20px;
+ display: flex;
+ /* 头像样式 */
+ .avatar {
+ margin-right: 10px;
+ }
+ /* 项目头部 */
+ .itemHeader {
+ display: flex;
+ align-items: flex-start;
+ gap: 12px;
+ margin-bottom: 12px;
+
+ /* 用户信息 */
+ .userInfo {
+ flex: 1;
+
+ .username {
+ font-size: 14px;
+ font-weight: 500;
+ color: #333;
+ line-height: 1.4;
+ }
+ }
+ }
+
+ /* 项目内容 */
+ .itemContent {
+ margin-bottom: 12px;
+ font-size: 12px;
+ .contentText {
+ color: #333;
+ line-height: 1.6;
+ margin-bottom: 8px;
+ word-wrap: break-word;
+ }
+
+ /* 图片容器 */
+ .imageContainer {
+ margin: 8px 0;
+ &::after {
+ content: "";
+ display: table;
+ clear: both;
+ }
+ .contentImage {
+ width: 60px;
+ height: 60px;
+ object-fit: cover;
+ border-radius: 4px;
+ margin-right: 8px;
+ margin-bottom: 8px;
+ cursor: pointer;
+ transition: transform 0.2s;
+ float: left;
+
+ &:hover {
+ transform: scale(1.05);
+ }
+ }
+ }
+
+ /* 蓝色链接 */
+ .blueLink {
+ color: #1890ff;
+ cursor: pointer;
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+ }
+
+ /* 项目底部 */
+ .itemFooter {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+
+ /* 时间信息 */
+ .timeInfo {
+ font-size: 12px;
+ color: #999;
+ }
+
+ /* 操作按钮区域 */
+ .actions {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+
+ .actionButton {
+ padding: 4px 8px;
+ color: #666;
+
+ &:hover {
+ color: #1890ff;
+ background-color: #f0f8ff;
+ }
+
+ .anticon {
+ font-size: 14px;
+ }
+ }
+ }
+ }
+
+ // 点赞和评论交互区域
+ .interactionArea {
+ margin-top: 8px;
+ padding: 8px 12px;
+ background-color: #f7f7f7;
+ border-radius: 4px;
+ font-size: 13px;
+
+ .likeArea {
+ display: flex;
+ align-items: center;
+ margin-bottom: 4px;
+
+ .likeIcon {
+ color: #ff6b6b;
+ margin-right: 6px;
+ font-size: 12px;
+ }
+
+ .likeList {
+ color: #576b95;
+
+ span {
+ cursor: pointer;
+
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+ }
+ }
+
+ .commentArea {
+ .commentItem {
+ margin-bottom: 2px;
+
+ .commentUser {
+ color: #576b95;
+ cursor: pointer;
+
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+
+ .commentSeparator {
+ color: #666;
+ }
+
+ .commentContent {
+ color: #333;
+ flex: 1;
+ }
+
+ .deleteCommentBtn {
+ opacity: 1;
+ transition: opacity 0.2s;
+ margin-left: 8px;
+ padding: 0;
+ height: auto;
+ min-width: auto;
+ display: inline-block;
+ }
+ }
+ }
+ }
+ // 评论输入框样式
+ .commentInputArea {
+ background-color: #f8f9fa;
+ border-radius: 8px;
+ border: 1px solid #e9ecef;
+
+ .commentInput {
+ border: none;
+ background: transparent;
+ resize: none;
+ font-size: 12px;
+ color: #333;
+
+ &:focus {
+ box-shadow: none;
+ }
+ }
+
+ .commentInputActions {
+ text-align: right;
+ padding-right: 10px;
+ padding-bottom: 10px;
+ .sendCommentBtn {
+ height: 28px;
+ font-size: 12px;
+ }
+ }
+ }
+ }
+ }
+
+ /* 空状态样式 */
+ .emptyText {
+ padding: 20px;
+ text-align: center;
+ color: #999;
+ font-size: 14px;
+ margin: 0;
+ }
+
+ /* 加载更多样式 */
+ .loadingMore {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 16px;
+ color: #666;
+ font-size: 14px;
+ gap: 8px;
+
+ .anticon {
+ margin-right: 4px;
+ }
+ }
+ }
+}
+
+/* ===== 图片预览Modal样式 ===== */
+.imagePreviewModal {
+ :global(.ant-modal-content) {
+ background: transparent;
+ box-shadow: none;
+ }
+
+ :global(.ant-modal-header) {
+ display: none;
+ }
+
+ :global(.ant-modal-close) {
+ position: fixed;
+ top: 20px;
+ right: 20px;
+ z-index: 1001;
+ color: white;
+ font-size: 24px;
+
+ &:hover {
+ background-color: rgba(255, 255, 255, 0.1);
+ }
+ }
+
+ :global(.ant-modal-body) {
+ padding: 0;
+ }
+}
+
+.previewContainer {
+ position: relative;
+ width: 100%;
+ height: 100vh;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: rgba(0, 0, 0, 0.9);
+
+ .previewImage {
+ max-width: 90vw;
+ max-height: 90vh;
+ object-fit: contain;
+ border-radius: 8px;
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
+ }
+
+ .navButton {
+ position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
+ background: rgba(0, 0, 0, 0.5);
+ border: none;
+ color: white;
+ font-size: 24px;
+ width: 50px;
+ height: 50px;
+ border-radius: 50%;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: all 0.3s;
+ z-index: 1000;
+
+ &:hover {
+ background: rgba(0, 0, 0, 0.7);
+ transform: translateY(-50%) scale(1.1);
+ }
+
+ &.prevButton {
+ left: 20px;
+ }
+
+ &.nextButton {
+ right: 20px;
+ }
+ }
+
+ .imageCounter {
+ position: absolute;
+ bottom: 20px;
+ left: 50%;
+ transform: translateX(-50%);
+ background: rgba(0, 0, 0, 0.7);
+ color: white;
+ padding: 8px 16px;
+ border-radius: 20px;
+ font-size: 14px;
+ z-index: 1000;
+ }
+}
diff --git a/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.tsx b/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.tsx
new file mode 100644
index 00000000..f7e054af
--- /dev/null
+++ b/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.tsx
@@ -0,0 +1,155 @@
+import React, { useState, useEffect } from "react";
+import { Collapse } from "antd";
+import { ChromeOutlined } from "@ant-design/icons";
+import { MomentList } from "./components/friendCard";
+
+import dayjs from "dayjs";
+import styles from "./index.module.scss";
+import { fetchFriendsCircleData } from "./api";
+import { useCkChatStore } from "@/store/module/ckchat/ckchat";
+import { useWeChatStore } from "@/store/module/weChat/weChat";
+
+interface FriendsCircleProps {
+ wechatFriendId?: number;
+}
+
+const FriendsCircle: React.FC = ({ wechatFriendId }) => {
+ const currentKf = useCkChatStore(state =>
+ state.kfUserList.find(kf => kf.id === state.kfSelected),
+ );
+ const { clearMomentCommon, updateMomentCommonLoading } = useWeChatStore();
+ const MomentCommon = useWeChatStore(state => state.MomentCommon);
+ const MomentCommonLoading = useWeChatStore(
+ state => state.MomentCommonLoading,
+ );
+
+ // 页面重新渲染时重置MomentCommonLoading状态
+ useEffect(() => {
+ updateMomentCommonLoading(false);
+ }, []);
+
+ // 状态管理
+ const [expandedKeys, setExpandedKeys] = useState([]);
+
+ // 加载更多我的朋友圈
+ const loadMomentData = async (loadMore: boolean = false) => {
+ updateMomentCommonLoading(true);
+ // 加载数据;
+ const requestData = {
+ cmdType: "CmdFetchMoment",
+ wechatAccountId: currentKf?.id || 0,
+ wechatFriendId: wechatFriendId || 0,
+ createTimeSec: Math.floor(dayjs().subtract(2, "month").valueOf() / 1000),
+ prevSnsId: loadMore
+ ? Number(MomentCommon[MomentCommon.length - 1]?.snsId) || 0
+ : 0,
+ count: 10,
+ isTimeline: expandedKeys.includes("1"),
+ seq: Date.now(),
+ };
+ await fetchFriendsCircleData(requestData);
+ };
+
+ // 处理折叠面板展开/收起
+ const handleCollapseChange = (keys: string | string[]) => {
+ const keyArray = Array.isArray(keys) ? keys : [keys];
+ setExpandedKeys(keyArray);
+ if (!MomentCommonLoading && keys.length > 0) {
+ clearMomentCommon();
+ loadMomentData(false);
+ }
+ };
+
+ // 格式化时间戳
+ const formatTime = (timestamp: number) => {
+ const date = new Date(timestamp * 1000);
+ return date.toLocaleString("zh-CN", {
+ year: "numeric",
+ month: "2-digit",
+ day: "2-digit",
+ hour: "2-digit",
+ minute: "2-digit",
+ });
+ };
+
+ const collapseItems = [
+ {
+ key: "1",
+ label: (
+
+

+
我的朋友圈
+
+ ),
+ children: (
+
+ ),
+ },
+ {
+ key: "2",
+ label: (
+
+
+ 朋友圈广场
+
+ ),
+ children: (
+
+ ),
+ },
+ ...(wechatFriendId
+ ? [
+ {
+ key: "3",
+ label: (
+
+
+ 好友朋友圈
+
+ ),
+ children: (
+
+ ),
+ },
+ ]
+ : []),
+ ];
+
+ return (
+
+ {/* 可折叠的特殊模块,包含所有朋友圈数据 */}
+
+
+ );
+};
+
+export default FriendsCircle;
diff --git a/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/index.tsx b/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/index.tsx
index dd072845..37516986 100644
--- a/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/index.tsx
+++ b/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/index.tsx
@@ -1,13 +1,9 @@
-import React, { useState } from "react";
+import React, { useEffect, useState } from "react";
import { Input, Skeleton } from "antd";
-import {
- SearchOutlined,
- UserOutlined,
- ChromeOutlined,
- MessageOutlined,
-} from "@ant-design/icons";
+import { SearchOutlined, ChromeOutlined } from "@ant-design/icons";
import WechatFriends from "./WechatFriends";
import MessageList from "./MessageList/index";
+import FriendsCircle from "./FriendsCicle";
import styles from "./SidebarMenu.module.scss";
import { useCkChatStore } from "@/store/module/ckchat/ckchat";
interface SidebarMenuProps {
@@ -18,6 +14,7 @@ const SidebarMenu: React.FC = ({ loading = false }) => {
const searchKeyword = useCkChatStore(state => state.searchKeyword);
const setSearchKeyword = useCkChatStore(state => state.setSearchKeyword);
const clearSearchKeyword = useCkChatStore(state => state.clearSearchKeyword);
+ const kfSelected = useCkChatStore(state => state.kfSelected);
const [activeTab, setActiveTab] = useState("chats");
@@ -29,7 +26,9 @@ const SidebarMenu: React.FC = ({ loading = false }) => {
clearSearchKeyword();
};
- // 过滤逻辑已移至store中,这里直接使用store返回的已过滤数据
+ useEffect(() => {
+ setActiveTab("chats");
+ }, [kfSelected]);
// 渲染骨架屏
const renderSkeleton = () => (
@@ -97,23 +96,22 @@ const SidebarMenu: React.FC = ({ loading = false }) => {
className={`${styles.tabItem} ${activeTab === "chats" ? styles.active : ""}`}
onClick={() => setActiveTab("chats")}
>
-
聊天