feat(wechat): 添加朋友圈功能支持

- 在微信状态管理中新增朋友圈相关状态和方法
- 实现朋友圈数据获取、展示和交互功能
- 添加朋友圈API接口和WebSocket消息处理
- 优化朋友圈UI展示和样式
This commit is contained in:
超级老白兔
2025-09-17 10:20:31 +08:00
parent 18b2735f80
commit 8b2c24d7a1
7 changed files with 338 additions and 29 deletions

View File

@@ -1,6 +1,117 @@
import request2 from "@/api/request2";
import request from "@/api/request";
// 静音聊天会话
// export const muteChatSession = (chatId: string): Promise<void> => {
// return request2(`/v1/chats/${chatId}/mute`, {}, "PUT");
// };
// 朋友圈相关的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();
const requestData = {
cmdType: "CmdFetchMoment",
wechatAccountId: params.wechatAccountId,
wechatFriendId: params.wechatFriendId || 0,
createTimeSec: params.createTimeSec || Math.floor(Date.now() / 1000),
prevSnsId: params.prevSnsId || 0,
count: params.count || 10,
isTimeline: params.isTimeline || false,
seq: params.seq || Date.now(),
};
sendCommand("CmdFetchMoment", requestData);
};
// 点赞朋友圈
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);
};

View File

@@ -55,7 +55,11 @@
display: flex;
align-items: center;
gap: 6px;
.avatar {
width: 20px;
height: 20px;
border-radius: 5px;
}
/* 特殊头像样式 */
.specialAvatar {
background-color: #1890ff;
@@ -174,7 +178,7 @@
margin-bottom: 8px;
cursor: pointer;
transition: transform 0.2s;
&:hover {
transform: scale(1.05);
}
@@ -246,10 +250,10 @@
.likeList {
color: #576b95;
span {
cursor: pointer;
&:hover {
text-decoration: underline;
}
@@ -265,7 +269,7 @@
.commentUser {
color: #576b95;
cursor: pointer;
&:hover {
text-decoration: underline;
}
@@ -316,11 +320,11 @@
background: transparent;
box-shadow: none;
}
:global(.ant-modal-header) {
display: none;
}
:global(.ant-modal-close) {
position: fixed;
top: 20px;
@@ -328,12 +332,12 @@
z-index: 1001;
color: white;
font-size: 24px;
&:hover {
background-color: rgba(255, 255, 255, 0.1);
}
}
:global(.ant-modal-body) {
padding: 0;
}
@@ -347,7 +351,7 @@
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.9);
.previewImage {
max-width: 90vw;
max-height: 90vh;
@@ -355,7 +359,7 @@
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
}
.navButton {
position: absolute;
top: 50%;
@@ -373,21 +377,21 @@
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;

View File

@@ -12,6 +12,8 @@ import {
import { InfiniteScroll } from "antd-mobile";
import styles from "./index.module.scss";
import { FriendsCircleItem, PaginationParams } from "./index.data";
import { useCkChatStore } from "@/store/module/ckchat/ckchat";
// 模拟朋友圈数据
const mockFriendsCircleData: FriendsCircleItem[] = [
{
@@ -96,6 +98,11 @@ const mockFriendsCircleData: FriendsCircleItem[] = [
];
const FriendsCircle: React.FC = () => {
const currentKf = useCkChatStore(state =>
state.kfUserList.find(kf => kf.id === state.kfSelected),
);
console.log(currentKf);
// 状态管理
const [myCircleData, setMyCircleData] = useState<FriendsCircleItem[]>([]);
const [squareData, setSquareData] = useState<FriendsCircleItem[]>([]);
@@ -466,7 +473,11 @@ const FriendsCircle: React.FC = () => {
key: "1",
label: (
<div className={styles.collapseHeader}>
<ChromeOutlined style={{ fontSize: 20 }} />
<img
className={styles.avatar}
src={currentKf?.avatar}
alt="客服头像"
/>
<span className={styles.specialText}></span>
</div>
),
@@ -476,7 +487,7 @@ const FriendsCircle: React.FC = () => {
key: "2",
label: (
<div className={styles.collapseHeader}>
<AppstoreOutlined style={{ fontSize: 20 }} />
<ChromeOutlined style={{ fontSize: 20 }} />
<span className={styles.specialText}>广</span>
</div>
),

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,6 @@
import { ChatRecord, ContractData, weChatGroup } from "@/pages/pc/ckbox/data";
import { FriendsCircleItem } from "@/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.data";
// 微信聊天相关的类型定义
export interface WeChatState {
// 当前选中的联系人/群组
@@ -13,6 +15,11 @@ export interface WeChatState {
isLoadingData: boolean;
currentGroupMembers: any[];
// 朋友圈数据
MomentOfKf: FriendsCircleItem[]; // 客服自己的朋友圈
MomentOfSquare: FriendsCircleItem[]; // 朋友圈广场
MomentOfFriend: FriendsCircleItem[]; // 好友的朋友圈
// Actions
setCurrentContact: (
contract: ContractData | weChatGroup,
@@ -30,4 +37,13 @@ export interface WeChatState {
setVideoUrl: (messageId: number, videoUrl: string) => void;
addMessage: (message: ChatRecord) => void;
receivedMsg: (message: ChatRecord) => void;
// 朋友圈相关方法
setMomentOfKf: (moments: FriendsCircleItem[]) => void;
setMomentOfSquare: (moments: FriendsCircleItem[]) => void;
setMomentOfFriend: (moments: FriendsCircleItem[]) => void;
addMomentOfKf: (moments: FriendsCircleItem[]) => void;
addMomentOfSquare: (moments: FriendsCircleItem[]) => void;
addMomentOfFriend: (moments: FriendsCircleItem[]) => void;
clearAllMoments: () => void;
}

View File

@@ -273,6 +273,45 @@ export const useWeChatStore = create<WeChatState>()(
messagesLoading: false,
});
},
// 朋友圈相关方法
setMomentOfKf: moments => {
set({ MomentOfKf: moments });
},
setMomentOfSquare: moments => {
set({ MomentOfSquare: moments });
},
setMomentOfFriend: moments => {
set({ MomentOfFriend: moments });
},
addMomentOfKf: moments => {
set(state => ({
MomentOfKf: [...state.MomentOfKf, ...moments],
}));
},
addMomentOfSquare: moments => {
set(state => ({
MomentOfSquare: [...state.MomentOfSquare, ...moments],
}));
},
addMomentOfFriend: moments => {
set(state => ({
MomentOfFriend: [...state.MomentOfFriend, ...moments],
}));
},
clearAllMoments: () => {
set({
MomentOfKf: [],
MomentOfSquare: [],
MomentOfFriend: [],
});
},
}),
{
name: "wechat-storage",

View File

@@ -3,8 +3,7 @@ import { deepCopy } from "@/utils/common";
import { WebSocketMessage } from "./websocket";
import { getkfUserList, asyncKfUserList } from "@/store/module/ckchat/ckchat";
import { Messages } from "./msg.data";
import { useWeChatStore } from "@/store/module/weChat/weChat";
import { useWeChatStore } from "../weChat/weChat";
// 消息处理器类型定义
type MessageHandler = (message: WebSocketMessage) => void;
const setVideoUrl = useWeChatStore.getState().setVideoUrl;
@@ -77,7 +76,54 @@ const messageHandlers: Record<string, MessageHandler> = {
CmdDownloadVideoResult: message => {
// 在这里添加具体的处理逻辑
setVideoUrl(message.friendMessageId, message.url);
console.log("视频下载结果:", message);
// setVideoUrl(message.friendMessageId, message.url);
},
// 朋友圈数据响应处理
CmdFetchMomentResult: message => {
console.log("朋友圈数据响应", message);
const { wechatFriendId, wechatAccountId, result, isTimeline, seq } =
message;
const {
setMomentOfKf,
setMomentOfSquare,
setMomentOfFriend,
addMomentOfKf,
addMomentOfSquare,
addMomentOfFriend,
} = useWeChatStore.getState();
if (result && Array.isArray(result)) {
// 判断是否为第一页数据通过seq或数据长度
const isFirstPage = result.length > 0;
// 根据wechatFriendId和isTimeline参数判断朋友圈类型
if (wechatFriendId === 0) {
if (isTimeline) {
// 朋友圈广场
if (isFirstPage) {
setMomentOfSquare(result);
} else {
addMomentOfSquare(result);
}
} else {
// 客服自己的朋友圈
if (isFirstPage) {
setMomentOfKf(result);
} else {
addMomentOfKf(result);
}
}
} else {
// 指定好友的朋友圈
if (isFirstPage) {
setMomentOfFriend(result);
} else {
addMomentOfFriend(result);
}
}
}
},
// 可以继续添加更多处理器...