refactor(ckbox): 统一联系人数据结构并简化聊天会话处理
- 将ContactData接口添加索引签名以支持动态属性 - 移除ChatSession接口,直接使用ContactData作为聊天会话类型 - 简化组件间数据传递和状态管理 - 更新相关组件props类型定义
This commit is contained in:
48
Cunkebao/src/pages/pc/ckbox/components/MessageList/data.ts
Normal file
48
Cunkebao/src/pages/pc/ckbox/components/MessageList/data.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
// 联系人数据接口
|
||||
export interface ContactData {
|
||||
id?: number;
|
||||
wechatAccountId: number;
|
||||
wechatId: string;
|
||||
alias: string;
|
||||
conRemark: string;
|
||||
nickname: string;
|
||||
quanPin: string;
|
||||
avatar?: string;
|
||||
gender: number;
|
||||
region: string;
|
||||
addFrom: number;
|
||||
phone: string;
|
||||
labels: string[];
|
||||
signature: string;
|
||||
accountId: number;
|
||||
extendFields: null;
|
||||
city?: string;
|
||||
lastUpdateTime: string;
|
||||
isPassed: boolean;
|
||||
tenantId: number;
|
||||
groupId: number;
|
||||
thirdParty: null;
|
||||
additionalPicture: string;
|
||||
desc: string;
|
||||
config: null;
|
||||
lastMessageTime: number;
|
||||
unreadCount: number;
|
||||
duplicate: boolean;
|
||||
[key: string]: any;
|
||||
}
|
||||
//聊天会话类型
|
||||
export type ChatType = "private" | "group";
|
||||
// 聊天会话接口
|
||||
export interface ChatSession {
|
||||
id: number;
|
||||
type: ChatType;
|
||||
name: string;
|
||||
avatar?: string;
|
||||
lastMessage: string;
|
||||
lastTime: string;
|
||||
unreadCount: number;
|
||||
online: boolean;
|
||||
members?: string[];
|
||||
pinned?: boolean;
|
||||
muted?: boolean;
|
||||
}
|
||||
@@ -2,17 +2,17 @@ import React from "react";
|
||||
import { List, Avatar, Badge } from "antd";
|
||||
import { UserOutlined, TeamOutlined } from "@ant-design/icons";
|
||||
import dayjs from "dayjs";
|
||||
import { ChatSession } from "@/pages/pc/ckbox/data";
|
||||
import { ContactData } from "./data";
|
||||
import styles from "./MessageList.module.scss";
|
||||
|
||||
interface MessageListProps {
|
||||
sessions: ChatSession[];
|
||||
currentChat: ChatSession | null;
|
||||
onChatSelect: (chat: ChatSession) => void;
|
||||
chatSessions: ContactData[];
|
||||
currentChat: ContactData;
|
||||
onChatSelect: (chat: ContactData) => void;
|
||||
}
|
||||
|
||||
const MessageList: React.FC<MessageListProps> = ({
|
||||
sessions,
|
||||
chatSessions,
|
||||
currentChat,
|
||||
onChatSelect,
|
||||
}) => {
|
||||
@@ -35,7 +35,7 @@ const MessageList: React.FC<MessageListProps> = ({
|
||||
return (
|
||||
<div className={styles.messageList}>
|
||||
<List
|
||||
dataSource={sessions}
|
||||
dataSource={chatSessions}
|
||||
renderItem={session => (
|
||||
<List.Item
|
||||
className={`${styles.messageItem} ${
|
||||
@@ -49,7 +49,7 @@ const MessageList: React.FC<MessageListProps> = ({
|
||||
size={48}
|
||||
src={session.avatar}
|
||||
icon={
|
||||
session.type === "group" ? (
|
||||
session?.type === "group" ? (
|
||||
<TeamOutlined />
|
||||
) : (
|
||||
<UserOutlined />
|
||||
@@ -59,18 +59,15 @@ const MessageList: React.FC<MessageListProps> = ({
|
||||
</Badge>
|
||||
<div className={styles.messageDetails}>
|
||||
<div className={styles.messageHeader}>
|
||||
<div className={styles.messageName}>{session.name}</div>
|
||||
<div className={styles.messageName}>{session.nickname}</div>
|
||||
<div className={styles.messageTime}>
|
||||
{formatTime(session.lastTime)}
|
||||
{formatTime(session?.lastTime || "")}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.messageContent}>
|
||||
<div className={styles.lastMessage}>
|
||||
{session.lastMessage}
|
||||
{session?.lastMessage}
|
||||
</div>
|
||||
{session.online && (
|
||||
<div className={styles.onlineIndicator}>在线</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,7 @@ import styles from "./ContactListSimple.module.scss";
|
||||
interface ContactListSimpleProps {
|
||||
contacts: ContactData[];
|
||||
onContactClick: (contact: ContactData) => void;
|
||||
selectedContactId?: number;
|
||||
selectedContactId?: ContactData;
|
||||
}
|
||||
|
||||
const ContactListSimple: React.FC<ContactListSimpleProps> = ({
|
||||
@@ -24,18 +24,16 @@ const ContactListSimple: React.FC<ContactListSimpleProps> = ({
|
||||
<List.Item
|
||||
key={contact.id}
|
||||
onClick={() => onContactClick(contact)}
|
||||
className={`${styles.contactItem} ${contact.id === selectedContactId ? styles.selected : ""}`}
|
||||
className={`${styles.contactItem} ${contact.id === selectedContactId?.id ? styles.selected : ""}`}
|
||||
>
|
||||
<div className={styles.avatarContainer}>
|
||||
<Badge dot={contact.online} color="green" offset={[-5, 5]}>
|
||||
<Avatar
|
||||
src={contact.avatar}
|
||||
icon={
|
||||
!contact.avatar && <span>{contact.nickname.charAt(0)}</span>
|
||||
}
|
||||
className={styles.avatar}
|
||||
/>
|
||||
</Badge>
|
||||
<Avatar
|
||||
src={contact.avatar}
|
||||
icon={
|
||||
!contact.avatar && <span>{contact.nickname.charAt(0)}</span>
|
||||
}
|
||||
className={styles.avatar}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.contactInfo}>
|
||||
<div className={styles.name}>{contact.nickname}</div>
|
||||
|
||||
@@ -28,6 +28,7 @@ export interface ContactData {
|
||||
lastMessageTime: number;
|
||||
unreadCount: number;
|
||||
duplicate: boolean;
|
||||
[key: string]: any;
|
||||
}
|
||||
//聊天会话类型
|
||||
export type ChatType = "private" | "group";
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
TeamOutlined,
|
||||
MessageOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { ContactData, ChatSession } from "./data";
|
||||
import { ContactData } from "./data";
|
||||
import WechatFriendsModule from "./WechatFriendsModule";
|
||||
import MessageList from "../MessageList/index";
|
||||
import styles from "./SidebarMenu.module.scss";
|
||||
@@ -16,10 +16,10 @@ const { TabPane } = Tabs;
|
||||
|
||||
interface SidebarMenuProps {
|
||||
contacts: ContactData[];
|
||||
chatSessions: ChatSession[];
|
||||
currentChat: ChatSession | null;
|
||||
chatSessions: ContactData[];
|
||||
currentChat: ContactData;
|
||||
onContactClick: (contact: ContactData) => void;
|
||||
onChatSelect: (chat: ChatSession) => void;
|
||||
onChatSelect: (chat: ContactData) => void;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ const SidebarMenu: React.FC<SidebarMenuProps> = ({
|
||||
const getFilteredSessions = () => {
|
||||
if (!searchText) return chatSessions;
|
||||
return chatSessions.filter(session =>
|
||||
session.name.toLowerCase().includes(searchText.toLowerCase()),
|
||||
session.nickname.toLowerCase().includes(searchText.toLowerCase()),
|
||||
);
|
||||
};
|
||||
|
||||
@@ -83,9 +83,9 @@ const SidebarMenu: React.FC<SidebarMenuProps> = ({
|
||||
key="chats"
|
||||
>
|
||||
<MessageList
|
||||
sessions={getFilteredSessions()}
|
||||
currentChat={currentChat}
|
||||
chatSessions={getFilteredSessions()}
|
||||
onChatSelect={onChatSelect}
|
||||
currentChat={currentChat}
|
||||
/>
|
||||
</TabPane>
|
||||
<TabPane
|
||||
@@ -100,7 +100,7 @@ const SidebarMenu: React.FC<SidebarMenuProps> = ({
|
||||
<WechatFriendsModule
|
||||
contacts={getFilteredContacts()}
|
||||
onContactClick={onContactClick}
|
||||
selectedContactId={currentChat?.id.split("_")[1]}
|
||||
selectedContactId={currentChat}
|
||||
/>
|
||||
</TabPane>
|
||||
<TabPane
|
||||
|
||||
@@ -28,6 +28,7 @@ export interface ContactData {
|
||||
lastMessageTime: number;
|
||||
unreadCount: number;
|
||||
duplicate: boolean;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,8 +2,7 @@ import React, { useState, useEffect } from "react";
|
||||
import { Layout, Button, Space, message, Tooltip } from "antd";
|
||||
import { InfoCircleOutlined, MessageOutlined } from "@ant-design/icons";
|
||||
import dayjs from "dayjs";
|
||||
import { ChatSession } from "./data";
|
||||
import { ContactData } from "./components/SidebarMenu/data";
|
||||
import { ContactData } from "./data";
|
||||
import ChatWindow from "./components/ChatWindow/index";
|
||||
import SidebarMenu from "./components/SidebarMenu/index";
|
||||
import styles from "./index.module.scss";
|
||||
@@ -16,8 +15,8 @@ import { chatInitAPIdata } from "./main";
|
||||
const CkboxPage: React.FC = () => {
|
||||
const [messageApi, contextHolder] = message.useMessage();
|
||||
const [contacts, setContacts] = useState<any[]>([]);
|
||||
const [chatSessions, setChatSessions] = useState<ChatSession[]>([]);
|
||||
const [currentChat, setCurrentChat] = useState<ChatSession | null>(null);
|
||||
const [chatSessions, setChatSessions] = useState<ContactData[]>([]);
|
||||
const [currentChat, setCurrentChat] = useState<ContactData | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [showProfile, setShowProfile] = useState(true);
|
||||
const { login2 } = useUserStore();
|
||||
@@ -55,18 +54,8 @@ const CkboxPage: React.FC = () => {
|
||||
|
||||
const handleContactClick = (contact: ContactData) => {
|
||||
// 查找或创建聊天会话
|
||||
let session = chatSessions.find(s => s.id === contact.id);
|
||||
const session = chatSessions.find(s => s.id === contact.id);
|
||||
if (!session) {
|
||||
session = {
|
||||
id: contact.id,
|
||||
type: "private",
|
||||
name: contact.nickname,
|
||||
avatar: contact.avatar,
|
||||
lastMessage: "",
|
||||
lastTime: dayjs().toISOString(),
|
||||
unreadCount: 0,
|
||||
online: contact.online,
|
||||
};
|
||||
setChatSessions(prev => [session!, ...prev]);
|
||||
}
|
||||
setCurrentChat(session);
|
||||
|
||||
Reference in New Issue
Block a user