feat(weChat): 添加朋友圈功能组件及样式
- 新增FriendsCircle组件实现朋友圈展示功能 - 添加朋友圈样式文件包含布局和交互样式 - 修改SidebarMenu组件支持朋友圈选项卡 - 根据kfSelected状态控制朋友圈选项卡显示
This commit is contained in:
@@ -0,0 +1,230 @@
|
||||
.friendsCircle {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
padding: 0;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.itemWrapper {
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
// 可折叠组件样式
|
||||
.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: 12px;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
// 当内容为空时的样式
|
||||
.emptyText {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 普通朋友圈项目样式
|
||||
.circleItem {
|
||||
background-color: #ffffff;
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
}
|
||||
|
||||
.itemHeader {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.userInfo {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.username {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.itemContent {
|
||||
margin-left: 52px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.contentText {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 8px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.imageContainer {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.contentImage {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
object-fit: cover;
|
||||
border-radius: 4px;
|
||||
margin-right: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.blueLink {
|
||||
color: #1890ff;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.itemFooter {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-left: 52px;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
// 滚动条样式
|
||||
.friendsCircle::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
.friendsCircle::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.friendsCircle::-webkit-scrollbar-thumb {
|
||||
background: #c1c1c1;
|
||||
border-radius: 3px;
|
||||
|
||||
&:hover {
|
||||
background: #a8a8a8;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
import React from "react";
|
||||
import { Avatar, Button, Collapse } from "antd";
|
||||
import { HeartOutlined, MessageOutlined } from "@ant-design/icons";
|
||||
import styles from "./index.module.scss";
|
||||
|
||||
// 朋友圈数据类型定义
|
||||
interface FriendsCircleItem {
|
||||
id: string;
|
||||
avatar: string;
|
||||
username: string;
|
||||
content: string;
|
||||
images?: string[];
|
||||
time: string;
|
||||
likes?: number;
|
||||
comments?: number;
|
||||
}
|
||||
|
||||
// 模拟朋友圈数据
|
||||
const mockFriendsCircleData: FriendsCircleItem[] = [
|
||||
{
|
||||
id: "1",
|
||||
avatar: "",
|
||||
username: "我的朋友圈",
|
||||
content: "",
|
||||
time: "",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
avatar: "",
|
||||
username: "朋友圈广场",
|
||||
content: "",
|
||||
time: "",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
avatar: "/public/assets/face/1.png",
|
||||
username: "老坑爹-解放双手,释放时间",
|
||||
content:
|
||||
"🎉🎊🎈欢迎小伙伴加入单群聊客宝地盘思慕斯蛋糕的小伙伴们的支持与信任!!!",
|
||||
images: ["/public/assets/face/1.png"],
|
||||
time: "2025年9月16日 13:48",
|
||||
likes: 0,
|
||||
comments: 0,
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
avatar: "/public/assets/face/1.png",
|
||||
username: "老坑爹-解放双手,释放时间",
|
||||
content: "一整年卡1好的产品有用户的好评是买卖说的再多不如用户的有说服力",
|
||||
images: ["/public/assets/face/1.png"],
|
||||
time: "2025年9月16日 11:33",
|
||||
likes: 0,
|
||||
comments: 0,
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
avatar: "/public/assets/face/1.png",
|
||||
username: "老坑爹-解放双手,释放时间",
|
||||
content:
|
||||
"两个小时637朵卡今天的努力也是给我自己最好的礼物🎁坚持就是胜利第二年开干。",
|
||||
images: ["/public/assets/face/1.png"],
|
||||
time: "2025年9月16日 11:03",
|
||||
likes: 0,
|
||||
comments: 0,
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
avatar: "/public/assets/face/1.png",
|
||||
username: "老坑爹-解放双手,释放时间",
|
||||
content: "老坑爹如果不幸苦,没有品质保障,客户会无限复购?",
|
||||
images: ["/public/assets/face/1.png"],
|
||||
time: "2025年9月16日 10:33",
|
||||
likes: 0,
|
||||
comments: 0,
|
||||
},
|
||||
];
|
||||
|
||||
const FriendsCircle: React.FC = () => {
|
||||
const handleLike = (id: string) => {
|
||||
console.log("点赞:", id);
|
||||
};
|
||||
|
||||
const handleComment = (id: string) => {
|
||||
console.log("评论:", id);
|
||||
};
|
||||
|
||||
const renderMyFriendsCircle = () => {
|
||||
// 显示部分朋友圈数据作为"我的朋友圈"
|
||||
const myCircleData = mockFriendsCircleData.slice(2, 4);
|
||||
|
||||
return (
|
||||
<div className={styles.myCircleContent}>
|
||||
{myCircleData.length > 0 ? (
|
||||
myCircleData.map(item => (
|
||||
<div key={item.id} className={styles.itemWrapper}>
|
||||
{renderNormalItem(item)}
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<p className={styles.emptyText}>暂无我的朋友圈内容</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const renderFriendsSquare = () => {
|
||||
// 显示剩余的朋友圈数据作为"朋友圈广场"
|
||||
const squareData = mockFriendsCircleData.slice(4);
|
||||
|
||||
return (
|
||||
<div className={styles.squareContent}>
|
||||
{squareData.length > 0 ? (
|
||||
squareData.map(item => (
|
||||
<div key={item.id} className={styles.itemWrapper}>
|
||||
{renderNormalItem(item)}
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<p className={styles.emptyText}>暂无朋友圈广场内容</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const collapseItems = [
|
||||
{
|
||||
key: "1",
|
||||
label: (
|
||||
<div className={styles.collapseHeader}>
|
||||
<Avatar size={32} className={styles.specialAvatar} />
|
||||
<span className={styles.specialText}>我的朋友圈</span>
|
||||
</div>
|
||||
),
|
||||
children: renderMyFriendsCircle(),
|
||||
},
|
||||
{
|
||||
key: "2",
|
||||
label: (
|
||||
<div className={styles.collapseHeader}>
|
||||
<div className={styles.groupAvatars}>
|
||||
<Avatar size={16} className={styles.groupAvatar} />
|
||||
<Avatar size={16} className={styles.groupAvatar} />
|
||||
<Avatar size={16} className={styles.groupAvatar} />
|
||||
<Avatar size={16} className={styles.groupAvatar} />
|
||||
</div>
|
||||
<span className={styles.specialText}>朋友圈广场</span>
|
||||
</div>
|
||||
),
|
||||
children: renderFriendsSquare(),
|
||||
},
|
||||
];
|
||||
|
||||
const renderNormalItem = (item: FriendsCircleItem) => {
|
||||
return (
|
||||
<div className={styles.circleItem}>
|
||||
<div className={styles.itemHeader}>
|
||||
<Avatar size={40} src={item.avatar} className={styles.avatar} />
|
||||
<div className={styles.userInfo}>
|
||||
<div className={styles.username}>{item.username}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.itemContent}>
|
||||
<div className={styles.contentText}>{item.content}</div>
|
||||
|
||||
{item.images && item.images.length > 0 && (
|
||||
<div className={styles.imageContainer}>
|
||||
{item.images.map((image, index) => (
|
||||
<img
|
||||
key={index}
|
||||
src={image}
|
||||
alt="朋友圈图片"
|
||||
className={styles.contentImage}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className={styles.blueLink}>查看图片</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.itemFooter}>
|
||||
<div className={styles.timeInfo}>{item.time}</div>
|
||||
<div className={styles.actions}>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
icon={<HeartOutlined />}
|
||||
onClick={() => handleLike(item.id)}
|
||||
className={styles.actionButton}
|
||||
/>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
icon={<MessageOutlined />}
|
||||
onClick={() => handleComment(item.id)}
|
||||
className={styles.actionButton}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.friendsCircle}>
|
||||
{/* 可折叠的特殊模块,包含所有朋友圈数据 */}
|
||||
<Collapse
|
||||
items={collapseItems}
|
||||
className={styles.collapseContainer}
|
||||
ghost
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default FriendsCircle;
|
||||
@@ -1,13 +1,9 @@
|
||||
import React, { 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<SidebarMenuProps> = ({ 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");
|
||||
|
||||
@@ -105,12 +102,14 @@ const SidebarMenu: React.FC<SidebarMenuProps> = ({ loading = false }) => {
|
||||
>
|
||||
<span>联系人</span>
|
||||
</div>
|
||||
<div
|
||||
className={`${styles.tabItem} ${activeTab === "groups" ? styles.active : ""}`}
|
||||
onClick={() => setActiveTab("groups")}
|
||||
>
|
||||
<span>朋友圈</span>
|
||||
</div>
|
||||
{kfSelected != 0 && (
|
||||
<div
|
||||
className={`${styles.tabItem} ${activeTab === "friendsCicle" ? styles.active : ""}`}
|
||||
onClick={() => setActiveTab("friendsCicle")}
|
||||
>
|
||||
<span>朋友圈</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -122,13 +121,8 @@ const SidebarMenu: React.FC<SidebarMenuProps> = ({ loading = false }) => {
|
||||
return <MessageList />;
|
||||
case "contracts":
|
||||
return <WechatFriends />;
|
||||
case "groups":
|
||||
return (
|
||||
<div className={styles.emptyState}>
|
||||
<ChromeOutlined style={{ fontSize: 48, color: "#ccc" }} />
|
||||
<p>暂无群组</p>
|
||||
</div>
|
||||
);
|
||||
case "friendsCicle":
|
||||
return <FriendsCircle />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user