feat: 在线: 会话中的消息分类筛选: 图片,视频,音频, 文件,邮件

dev/email
Lei OT 9 months ago
parent 9f37d32972
commit 8dd49be1cd

@ -61,7 +61,7 @@ const ChatListFilter = ({ ...props }) => {
onOpenChange={setOpenPopup}
title={
<div className='flex justify-between '>
<div>更多筛选</div>
<div>更多会话筛选</div>
<Button size='small' onClick={() => setOpenPopup(false)}>
&times;
</Button>

@ -0,0 +1,177 @@
import { createContext, useEffect, useState } from 'react';
import { Button, Tag, Radio, Popover, Form, Dropdown, Tabs, List, Image, Empty, Avatar } from 'antd';
import { FileSearchOutlined, FilterOutlined, FilterTwoTone } from '@ant-design/icons';
import { FilterIcon } from '@/components/Icons';
import { isEmpty, objectMapper, stringToColour } from '@/utils/commons';
import useConversationStore from '@/stores/ConversationStore';
import { useShallow } from 'zustand/react/shallow';
const CalColorStyle = (tag, outerStyle = true) => {
const color = stringToColour(tag);
const outerStyleObj = outerStyle ? { borderColor: `${color}66`, backgroundColor: `${color}0D` } : {};
return { color: `${color}`, ...outerStyleObj };
};
const MessageListFilter = ({ ...props }) => {
const activeMessages = useConversationStore(
useShallow((state) => (state.currentConversation.sn && state.activeConversations[state.currentConversation.sn] ? state.activeConversations[state.currentConversation.sn] : []))
);
const LongList = () => {
return <></>;
};
const Album = () => {
const data = (activeMessages || []).filter((item) => item.type === 'photo').reverse();
return (
<>
{data.length === 0 && <Empty description={false} />}
<div className='grid grid-cols-5 gap-2 max-h-96 overflow-y-auto'>
<Image.PreviewGroup className='my-4'>
{data.map((img) => (
<Image className='border object-cover' key={img.data.id} width={100} height={100} src={img.data.uri} />
))}
</Image.PreviewGroup>
</div>
</>
);
};
const Videos = () => {
// todo:
const data = (activeMessages || []).filter((item) => item.type === 'video').reverse();
return (
<>
{data.length === 0 && <Empty description={false} />}
<div className='grid grid-cols-3 gap-2 max-h-96 overflow-y-auto'>
{data.map((item) => (
<video controls controlsList='nodownload nofullscreen noremoteplayback' key={item.data.id} className='max-h-20'>
<source src={item?.data.videoURL} type='video/mp4' />
Your browser does not support HTML video.
</video>
))}
</div>
</>
);
};
const Audios = () => {
const data = (activeMessages || []).filter((item) => item.type === 'audio').reverse();
return (
<>
<List
className='max-h-96 overflow-y-auto'
itemLayout='horizontal'
dataSource={data}
renderItem={(item, index) => (
<List.Item actions={[item.localDate]}>
<List.Item.Meta
avatar={
<Avatar size='small' style={CalColorStyle(item.senderName)}>
{item.senderName.substring(0, 5)}
</Avatar>
}
/>
<audio controls src={item.data.uri} className='h-6'></audio>
</List.Item>
)}
/>
</>
);
};
const FileList = () => {
const data = (activeMessages || []).filter((item) => item.type === 'file').reverse();
return (
<>
{/* {data.length === 0 && <Empty />} */}
<List
className='max-h-96 overflow-y-auto'
itemLayout='horizontal'
dataSource={data}
renderItem={(item, index) => (
<List.Item actions={[item.localDate]}>
<List.Item.Meta
// avatar={<Avatar src={`https://api.dicebear.com/7.x/miniavs/svg?seed=${index}`} />}
avatar={
<Avatar size='small' style={CalColorStyle(item.sender)}>
{item.senderName}
</Avatar>
}
title={
<a href={item.data.uri} target='_blank' rel='noreferrer'>
{item.title} 🔗
</a>
}
description={item.text}
/>
{/* {item.text} */}
</List.Item>
)}
/>
</>
);
};
const EmailList = () => {
// todo:
const data = (activeMessages || []).filter((item) => item.type === 'email').reverse();
return (
<>
{/* {data.length === 0 && <Empty />} */}
<List
className='max-h-96 overflow-y-auto'
itemLayout='horizontal'
dataSource={data}
renderItem={({ emailOrigin, ...item }, index) => (
<List.Item actions={[item.localDate]}>
<List.Item.Meta
avatar={
<Avatar size='small' style={CalColorStyle(item.senderName)}>
{item.senderName.substring(0, 3)}
</Avatar>
}
title={emailOrigin.subject}
description={`To: ${emailOrigin.toEmail}`}
/>
{emailOrigin.abstract}
</List.Item>
)}
/>
</>
);
};
const [openPopup, setOpenPopup] = useState(false);
// todo:
return (
<>
<Popover
// overlayClassName={[mobile === undefined ? 'w-3/5' : 'w-full max-h-full'].join(' ')}
// destroyTooltipOnHide
placement='bottom'
overlayClassName='w-2/5 max-w-2/5 max-h-[70%]'
trigger={'click'}
open={openPopup}
onOpenChange={setOpenPopup}
content={
<>
<Tabs
defaultActiveKey='email'
size={'small'}
className='bg-white *:m-0 '
items={[
// { key: 'all', label: '', children: <LongList /> },
{ key: 'image', label: '图片', children: <Album /> },
{ key: 'video', label: '视频', children: <Videos /> },
{ key: 'audio', label: '音频', children: <Audios /> },
{ key: 'file', label: '文件', children: <FileList /> },
{ key: 'email', label: '邮件', children: <EmailList /> },
]}
/>
</>
}>
<Button icon={<FileSearchOutlined />} type='text' size='middle' title='消息记录' />
</Popover>
</>
);
};
export default MessageListFilter;

@ -4,6 +4,7 @@ import { Flex, Typography, Avatar, Alert, Button, Tooltip, Spin } from 'antd';
import { ReloadOutlined, ApiOutlined } from '@ant-design/icons';
import { LoadingOutlined } from '@ant-design/icons';
import ExpireTimeClock from './ExpireTimeClock';
import MessageListFilter from './Components/MessageListFilter';
const MessagesHeader = () => {
const userId = useAuthStore(state => state.loginUser.userId);
@ -59,6 +60,7 @@ const MessagesHeader = () => {
</Flex>
</Flex>
</Flex>
<MessageListFilter />
</>
);
};

Loading…
Cancel
Save