feat(朋友圈): 添加朋友圈功能相关组件和状态管理

- 新增朋友圈数据类型定义和接口
- 在状态管理中添加朋友圈相关状态
- 实现朋友圈图片预览功能
- 优化朋友圈样式和交互体验
This commit is contained in:
超级老白兔
2025-09-16 18:42:51 +08:00
parent d11ae4365c
commit 18b2735f80
6 changed files with 353 additions and 66 deletions

View File

@@ -0,0 +1,56 @@
// 评论数据类型
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 PaginationParams {
pageNum: number;
pageSize: number;
type: "my" | "square";
}

View File

@@ -172,6 +172,12 @@
border-radius: 4px;
margin-right: 8px;
margin-bottom: 8px;
cursor: pointer;
transition: transform 0.2s;
&:hover {
transform: scale(1.05);
}
}
}
@@ -303,3 +309,95 @@
}
}
}
/* ===== 图片预览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;
}
}

View File

@@ -1,72 +1,17 @@
import React, { useState, useEffect } from "react";
import { Avatar, Button, Collapse, Spin } from "antd";
import { Avatar, Button, Collapse, Spin, Modal } from "antd";
import { useWebSocketStore } from "@/store/module/websocket/websocket";
import {
HeartOutlined,
ChromeOutlined,
MessageOutlined,
LoadingOutlined,
AppstoreOutlined,
CloseOutlined,
} from "@ant-design/icons";
import { InfiniteScroll } from "antd-mobile";
import styles from "./index.module.scss";
// 评论数据类型
interface CommentItem {
commentArg: number;
commentId1: number;
commentId2: number;
commentTime: number;
content: string;
nickName: string;
wechatId: string;
}
// 点赞数据类型
interface LikeItem {
createTime: number;
nickName: string;
wechatId: string;
}
// 朋友圈实体数据类型
interface MomentEntity {
content: string;
createTime: number;
lat: number;
lng: number;
location: string;
objectType: number;
picSize: number;
resUrls: string[];
snsId: string;
urls: string[];
userName: string;
}
// 朋友圈数据类型定义
interface FriendsCircleItem {
commentList: CommentItem[];
createTime: number;
likeList: LikeItem[];
momentEntity: MomentEntity;
snsId: string;
type: number;
}
// API响应类型
interface ApiResponse {
list: FriendsCircleItem[];
total: number;
hasMore: boolean;
}
// 分页参数类型
interface PaginationParams {
pageNum: number;
pageSize: number;
type: "my" | "square";
}
import { FriendsCircleItem, PaginationParams } from "./index.data";
// 模拟朋友圈数据
const mockFriendsCircleData: FriendsCircleItem[] = [
{
@@ -162,10 +107,26 @@ const FriendsCircle: React.FC = () => {
const [squarePage, setSquarePage] = useState(1);
const [expandedKeys, setExpandedKeys] = useState<string[]>([]);
// 图片预览相关状态
const [previewVisible, setPreviewVisible] = useState(false);
const [previewImages, setPreviewImages] = useState<string[]>([]);
const [currentImageIndex, setCurrentImageIndex] = useState(0);
const { sendCommand } = useWebSocketStore.getState();
// const handleSend = async () => {
// const params = {
// wechatAccountId: contract.wechatAccountId,
// wechatChatroomId: contract?.chatroomId ? contract.id : 0,
// wechatFriendId: contract?.chatroomId ? 0 : contract.id,
// msgSubType: 0,
// msgType: 1,
// content: inputValue,
// };
// sendCommand("CmdSendMessage", params);
// };
// 模拟API调用函数
const fetchFriendsCircleData = async (
params: PaginationParams,
): Promise<ApiResponse> => {
const fetchFriendsCircleData = async (params: PaginationParams) => {
// 模拟网络延迟
await new Promise(resolve => setTimeout(resolve, 1000));
@@ -276,6 +237,34 @@ const FriendsCircle: React.FC = () => {
console.log("评论:", id);
};
// 处理图片预览
const handleImagePreview = (images: string[], index: number) => {
setPreviewImages(images);
setCurrentImageIndex(index);
setPreviewVisible(true);
};
// 关闭图片预览
const handleClosePreview = () => {
setPreviewVisible(false);
setPreviewImages([]);
setCurrentImageIndex(0);
};
// 切换到上一张图片
const handlePrevImage = () => {
setCurrentImageIndex(prev =>
prev > 0 ? prev - 1 : previewImages.length - 1,
);
};
// 切换到下一张图片
const handleNextImage = () => {
setCurrentImageIndex(prev =>
prev < previewImages.length - 1 ? prev + 1 : 0,
);
};
// 格式化时间戳
const formatTime = (timestamp: number) => {
const date = new Date(timestamp * 1000);
@@ -331,14 +320,11 @@ const FriendsCircle: React.FC = () => {
key={index}
src={image}
className={styles.contentImage}
onClick={() => handleImagePreview(images, index)}
/>
))}
</div>
)}
{images && images.length > 0 && (
<div className={styles.blueLink}></div>
)}
</div>
<div className={styles.itemFooter}>
@@ -508,6 +494,58 @@ const FriendsCircle: React.FC = () => {
activeKey={expandedKeys}
onChange={handleCollapseChange}
/>
{/* 图片预览Modal */}
<Modal
open={previewVisible}
footer={null}
onCancel={handleClosePreview}
width="100vw"
style={{ top: 0, paddingBottom: 0 }}
bodyStyle={{
padding: 0,
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center",
backgroundColor: "rgba(0, 0, 0, 0.9)",
}}
closeIcon={<CloseOutlined style={{ color: "white", fontSize: 24 }} />}
className={styles.imagePreviewModal}
>
<div className={styles.previewContainer}>
{previewImages.length > 0 && (
<>
<img
src={previewImages[currentImageIndex]}
alt="预览图片"
className={styles.previewImage}
/>
{previewImages.length > 1 && (
<>
<button
className={`${styles.navButton} ${styles.prevButton}`}
onClick={handlePrevImage}
>
</button>
<button
className={`${styles.navButton} ${styles.nextButton}`}
onClick={handleNextImage}
>
</button>
<div className={styles.imageCounter}>
{currentImageIndex + 1} / {previewImages.length}
</div>
</>
)}
</>
)}
</div>
</Modal>
</div>
);
};

File diff suppressed because one or more lines are too long

View File

@@ -24,6 +24,11 @@ export const useWeChatStore = create<WeChatState>()(
messagesLoading: false,
isLoadingData: false,
currentGroupMembers: [],
MomentOfKf: [], //客服自己的朋友圈
MomentOfSquare: [], //朋友圈广场
MomentOfFriend: [], //好友的朋友圈
//============方法列表============
//清空当前联系人
clearCurrentContact: () => {
set({ currentContract: null, currentMessages: [] });