开发: 成员聊天页面

This commit is contained in:
zhengw
2023-04-13 17:36:49 +08:00
parent e2b466042f
commit b2bf2ade21
27 changed files with 970 additions and 512 deletions

View File

@@ -17,7 +17,8 @@ export const ChatAgreeOrNot: React.FC<IProps> = (props) => {
alignItems: 'center',
}}
>
{props.msg_type == 'agree' ? '' : '不'}
{props.msg_type == 'agree' ? '' : '不'}
{props.msg_type == 'agree' ? '可以' : '将无法'}
</span>
</div>
);

View File

@@ -1,6 +1,8 @@
import { IChatItem } from '../ChatLogsType';
import { ChatAgreeOrNot } from './ChatAgreeOrNot';
import { ChatCard } from './ChatCard';
import { ChatCollect } from './ChatCollect';
import { ChatDocmsg } from './ChatDocmsg';
import { ChatEmotion } from './ChatEmotion';
import { ChatFile } from './ChatFile';
import { ChatImage } from './ChatImage';
@@ -11,45 +13,119 @@ import { ChatRecord } from './ChatRecord';
import { ChatRedpacket } from './ChatRedpacket';
import { ChatRevoke } from './ChatRevoke';
import { ChatText } from './ChatText';
import { ChatTodo } from './ChatTodo';
import { ChatVideo } from './ChatVideo';
import { ChatVoice } from './ChatVoice';
import { ChatVoiptext } from './ChatVoiptext';
import { ChatVote } from './ChatVote';
import { ChatWeapp } from './ChatWeapp';
import styles from './index.module.scss';
export const ChatBar: React.FC<IChatItem> = (props) => {
const { from, to, chat } = props;
if (chat?.msg_type == 'text') {
return <ChatText from={from} to={to} chat={chat}></ChatText>;
} else if (chat?.msg_type == 'file') {
return <ChatFile from={from} to={to} chat={chat}></ChatFile>;
} else if (chat?.msg_type == 'emotion') {
return <ChatEmotion from={from} to={to} chat={chat}></ChatEmotion>;
} else if (chat?.msg_type == 'card') {
return <ChatCard from={from} to={to} chat={chat}></ChatCard>;
} else if (chat?.msg_type == 'external_redpacket') {
return <ChatRedpacket from={from} to={to} chat={chat}></ChatRedpacket>;
} else if (chat?.msg_type == 'image') {
return <ChatImage from={from} to={to} chat={chat}></ChatImage>;
} else if (chat?.msg_type == 'link') {
return <ChatLink from={from} to={to} chat={chat}></ChatLink>;
} else if (chat?.msg_type == 'location') {
return <ChatLocation from={from} to={to} chat={chat}></ChatLocation>;
} else if (chat?.msg_type == 'video') {
return <ChatVideo from={from} to={to} chat={chat}></ChatVideo>;
} else if (chat?.msg_type == 'voice') {
return <ChatVoice from={from} to={to} chat={chat}></ChatVoice>;
} else if (chat?.msg_type == 'chatrecord') {
return <ChatRecord from={from} to={to} chat={chat}></ChatRecord>;
} else if (chat?.msg_type == 'meeting_voice_call') {
return <ChatMeetingVoiceCall from={from} to={to} chat={chat}></ChatMeetingVoiceCall>;
} else if (chat?.msg_type == 'voiptext') {
return <ChatVoiptext from={from} to={to} chat={chat}></ChatVoiptext>;
} else if (chat?.msg_type == 'weapp') {
return <ChatWeapp from={from} to={to} chat={chat}></ChatWeapp>;
} else if (chat?.msg_type == 'revoke') {
const chatContent = () => {
if (chat?.msg_type == 'text') {
return <ChatText from={from} to={to} chat={chat}></ChatText>;
} else if (chat?.msg_type == 'file') {
return <ChatFile from={from} to={to} chat={chat}></ChatFile>;
} else if (chat?.msg_type == 'emotion') {
return <ChatEmotion from={from} to={to} chat={chat}></ChatEmotion>;
} else if (chat?.msg_type == 'card') {
return <ChatCard from={from} to={to} chat={chat}></ChatCard>;
} else if (chat?.msg_type == 'external_redpacket' || chat?.msg_type == 'redpacket') {
return <ChatRedpacket from={from} to={to} chat={chat}></ChatRedpacket>;
} else if (chat?.msg_type == 'image') {
return <ChatImage from={from} to={to} chat={chat}></ChatImage>;
} else if (chat?.msg_type == 'link') {
return <ChatLink from={from} to={to} chat={chat}></ChatLink>;
} else if (chat?.msg_type == 'location') {
return <ChatLocation from={from} to={to} chat={chat}></ChatLocation>;
} else if (chat?.msg_type == 'video') {
return <ChatVideo from={from} to={to} chat={chat}></ChatVideo>;
} else if (chat?.msg_type == 'voice') {
return <ChatVoice from={from} to={to} chat={chat}></ChatVoice>;
} else if (chat?.msg_type == 'chatrecord') {
return <ChatRecord from={from} to={to} chat={chat}></ChatRecord>;
} else if (chat?.msg_type == 'meeting_voice_call') {
return <ChatMeetingVoiceCall from={from} to={to} chat={chat}></ChatMeetingVoiceCall>;
} else if (chat?.msg_type == 'voiptext') {
return <ChatVoiptext from={from} to={to} chat={chat}></ChatVoiptext>;
} else if (chat?.msg_type == 'weapp') {
return <ChatWeapp from={from} to={to} chat={chat}></ChatWeapp>;
} else if (chat?.msg_type == 'todo') {
return <ChatTodo from={from} to={to} chat={chat}></ChatTodo>;
} else if (chat?.msg_type == 'vote') {
return <ChatVote from={from} to={to} chat={chat}></ChatVote>;
} else if (chat?.msg_type == 'collect') {
return <ChatCollect from={from} to={to} chat={chat}></ChatCollect>;
} else if (chat?.msg_type == 'docmsg') {
return <ChatDocmsg from={from} to={to} chat={chat}></ChatDocmsg>;
} else {
return <></>;
}
};
if (chat?.msg_type == 'revoke') {
return <ChatRevoke></ChatRevoke>;
} else if (chat?.msg_type == 'agree' || chat?.msg_type == 'disagree') {
return <ChatAgreeOrNot msg_type={chat?.msg_type}></ChatAgreeOrNot>;
} else {
return (
<>
{/* {props.chat?.seq} */}
{props.from?.user_id == props.chat?.msg_from ? (
<div className={styles.chatRight}>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.from?.name}</div>
<div className={styles.content}>
{props.chat?.state == 0 ? (
<div className={styles.revokeMsg}></div>
) : null}
{chatContent()}
</div>
</div>
<div
className={styles.chatAvatar}
style={{ background: props.from?.avatar ? '#fff' : '' }}
>
{props.from?.avatar ? (
<img src={props.from?.avatar} alt="" />
) : props.from?.name ? (
props.from.name[0]
) : (
''
)}
</div>
</div>
) : (
<div className={styles.chatLeft}>
<div
className={styles.chatAvatar}
style={{ background: props.from?.avatar ? '#fff' : '' }}
>
{props.to?.avatar ? (
<img src={props.to?.avatar} alt="" />
) : props.to?.name ? (
props.to.name[0]
) : (
''
)}
</div>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.to?.name}</div>
<div className={styles.content}>
{props.chat?.state == 0 ? (
<div className={styles.revokeMsg}>
<span></span>
</div>
) : null}
{chatContent()}
</div>
</div>
</div>
)}
</>
);
}
return <div></div>;
};

View File

@@ -1,5 +1,4 @@
import { IChatItem } from '../ChatLogsType';
import styles from './index.module.scss';
export const ChatCard: React.FC<IChatItem> = (props) => {
function content() {
// <div style={{ display: 'flex' }}>
@@ -19,7 +18,9 @@ export const ChatCard: React.FC<IChatItem> = (props) => {
return (
<div style={{ display: 'flex', color: '#000', flexDirection: 'column', width: 200 }}>
<div style={{ wordBreak: 'break-all', paddingRight: 8 }}>{msg.corpname}</div>
<div style={{ color: '#999', borderTop: '1px solid #ddd' }}></div>
<div style={{ color: '#999', borderTop: '1px solid #ddd', marginTop: 8, paddingTop: 8 }}>
</div>
</div>
);
} catch (_e) {
@@ -31,27 +32,5 @@ export const ChatCard: React.FC<IChatItem> = (props) => {
}
}
return (
<>
{props.from?.user_id == props.chat?.msg_from ? (
<div className={styles.chatRight}>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.from?.name}</div>
<div className={styles.content}>{content()}</div>
</div>
<div className={styles.chatAvatar}>{props.from?.name[0]}</div>
</div>
) : (
<div className={styles.chatLeft}>
<div className={styles.chatAvatar}>
<img src={props.to?.cust_info.avatar} alt="" />
</div>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.to?.cust_info.name}</div>
<div className={styles.content}>{content()}</div>
</div>
</div>
)}
</>
);
return <>{content()}</>;
};

View File

@@ -0,0 +1,38 @@
import { IChatItem } from '../ChatLogsType';
export const ChatCollect: React.FC<IChatItem> = (props) => {
function content() {
try {
const msg = JSON.parse(props.chat?.collect as string);
return (
<div>
<div style={{ display: 'flex', color: '#000', flexDirection: 'column' }}>
<div style={{ wordBreak: 'break-all' }}>{msg.room_name}</div>
<div style={{ wordBreak: 'break-all' }}>{msg.creator}</div>
<div style={{ wordBreak: 'break-all' }}>{msg.title}</div>
<div
style={{ borderTop: '1px solid #ddd', color: '#999', marginTop: 8, paddingTop: 8 }}
>
</div>
</div>
</div>
);
} catch (_e) {
return (
<div>
<div style={{ display: 'flex', color: '#000', flexDirection: 'column' }}>
<div style={{ wordBreak: 'break-all' }}>{props.chat?.collect}</div>
<div
style={{ borderTop: '1px solid #ddd', color: '#999', marginTop: 8, paddingTop: 8 }}
>
</div>
</div>
</div>
);
}
}
return <>{content()}</>;
};

View File

@@ -0,0 +1,38 @@
import { IChatItem } from '../ChatLogsType';
export const ChatDocmsg: React.FC<IChatItem> = (props) => {
function content() {
try {
const msg = JSON.parse(props.chat?.doc as string);
return (
<a href={msg.link_url} target="_blank">
<div style={{ display: 'flex', color: '#000', flexDirection: 'column' }}>
<div style={{ wordBreak: 'break-all' }}>{msg.title}</div>
<div style={{ wordBreak: 'break-all' }}>{msg.link_url}</div>
<div style={{ wordBreak: 'break-all' }}>{msg.doc_creator}</div>
<div
style={{ borderTop: '1px solid #ddd', color: '#999', marginTop: 8, paddingTop: 8 }}
>
线
</div>
</div>
</a>
);
} catch (_e) {
return (
<div>
<div style={{ display: 'flex', color: '#000', flexDirection: 'column' }}>
<div style={{ wordBreak: 'break-all' }}>{props.chat?.doc}</div>
<div
style={{ borderTop: '1px solid #ddd', color: '#999', marginTop: 8, paddingTop: 8 }}
>
线
</div>
</div>
</div>
);
}
}
return <>{content()}</>;
};

View File

@@ -39,27 +39,5 @@ export const ChatEmotion: React.FC<IChatItem> = (props) => {
}
}
return (
<>
{props.from?.user_id == props.chat?.msg_from ? (
<div className={styles.chatRight}>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.from?.name}</div>
<div className={styles.content}>{content()}</div>
</div>
<div className={styles.chatAvatar}>{props.from?.name[0]}</div>
</div>
) : (
<div className={styles.chatLeft}>
<div className={styles.chatAvatar}>
<img src={props.to?.cust_info.avatar} alt="" />
</div>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.to?.cust_info.name}</div>
<div className={styles.content}>{content()}</div>
</div>
</div>
)}
</>
);
return <>{content()}</>;
};

View File

@@ -1,6 +1,5 @@
import { FileTextFilled } from '@ant-design/icons';
import { IChatItem } from '../ChatLogsType';
import styles from './index.module.scss';
export const ChatFile: React.FC<IChatItem> = (props) => {
function content() {
@@ -12,41 +11,19 @@ export const ChatFile: React.FC<IChatItem> = (props) => {
download={msg.file_name}
href={`/api/${msg.path}`}
>
<div style={{ wordBreak: 'break-all', paddingRight: 8 }}>{msg.file_name}</div>
<FileTextFilled style={{ fontSize: 40, color: '#FA9D3B', flexShrink: 0 }} />
<div style={{ wordBreak: 'break-all', paddingLeft: 12 }}>{msg.file_name}</div>
</a>
);
} catch (_e) {
return (
<div>
<div style={{ wordBreak: 'break-all', paddingRight: 8 }}>{props.chat?.content}</div>
<FileTextFilled style={{ fontSize: 40, color: '#FA9D3B', flexShrink: 0 }} />
<div style={{ wordBreak: 'break-all', paddingLeft: 12 }}>{props.chat?.content}</div>
</div>
);
}
}
return (
<>
{props.from?.user_id == props.chat?.msg_from ? (
<div className={styles.chatRight}>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.from?.name}</div>
<div className={styles.content}>{content()}</div>
</div>
<div className={styles.chatAvatar}>{props.from?.name[0]}</div>
</div>
) : (
<div className={styles.chatLeft}>
<div className={styles.chatAvatar}>
<img src={props.to?.cust_info.avatar} alt="" />
</div>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.to?.cust_info.name}</div>
<div className={styles.content}>{content()}</div>
</div>
</div>
)}
</>
);
return <>{content()}</>;
};

View File

@@ -42,27 +42,5 @@ export const ChatImage: React.FC<IChatItem> = (props) => {
}
}
return (
<>
{props.from?.user_id == props.chat?.msg_from ? (
<div className={styles.chatRight}>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.from?.name}</div>
<div className={styles.content}>{content()}</div>
</div>
<div className={styles.chatAvatar}>{props.from?.name[0]}</div>
</div>
) : (
<div className={styles.chatLeft}>
<div className={styles.chatAvatar}>
<img src={props.to?.cust_info.avatar} alt="" />
</div>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.to?.cust_info.name}</div>
<div className={styles.content}>{content()}</div>
</div>
</div>
)}
</>
);
return <>{content()}</>;
};

View File

@@ -1,6 +1,5 @@
import { IeSquareFilled } from '@ant-design/icons';
import { IChatItem } from '../ChatLogsType';
import styles from './index.module.scss';
export const ChatLink: React.FC<IChatItem> = (props) => {
function content() {
@@ -31,27 +30,5 @@ export const ChatLink: React.FC<IChatItem> = (props) => {
}
}
return (
<>
{props.from?.user_id == props.chat?.msg_from ? (
<div className={styles.chatRight}>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.from?.name}</div>
<div className={styles.content}>{content()}</div>
</div>
<div className={styles.chatAvatar}>{props.from?.name[0]}</div>
</div>
) : (
<div className={styles.chatLeft}>
<div className={styles.chatAvatar}>
<img src={props.to?.cust_info.avatar} alt="" />
</div>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.to?.cust_info.name}</div>
<div className={styles.content}>{content()}</div>
</div>
</div>
)}
</>
);
return <>{content()}</>;
};

View File

@@ -1,6 +1,5 @@
import { EnvironmentFilled } from '@ant-design/icons';
import { IChatItem } from '../ChatLogsType';
import styles from './index.module.scss';
export const ChatLocation: React.FC<IChatItem> = (props) => {
function content() {
@@ -8,49 +7,23 @@ export const ChatLocation: React.FC<IChatItem> = (props) => {
const msg = JSON.parse(props.chat?.content as string);
return (
<a
style={{ display: 'flex', color: '#000' }}
download={msg.file_name}
href={`/api/${msg.path}`}
>
<div style={{ wordBreak: 'break-all', paddingRight: 8 }}>
<div style={{ display: 'flex', color: '#000' }}>
<EnvironmentFilled style={{ fontSize: 40, color: '#FA9D3B', flexShrink: 0 }} />
<div style={{ wordBreak: 'break-all', paddingLeft: 12 }}>
<div>{msg.title}</div>
<div>{msg.address}</div>
</div>
<EnvironmentFilled style={{ fontSize: 40, color: '#FA9D3B', flexShrink: 0 }} />
</a>
</div>
);
} catch (_e) {
return (
<div>
<div style={{ wordBreak: 'break-all', paddingRight: 8 }}>{props.chat?.content}</div>
<EnvironmentFilled style={{ fontSize: 40, color: '#FA9D3B', flexShrink: 0 }} />
<div style={{ wordBreak: 'break-all', paddingLeft: 12 }}>{props.chat?.content}</div>
</div>
);
}
}
return (
<>
{props.from?.user_id == props.chat?.msg_from ? (
<div className={styles.chatRight}>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.from?.name}</div>
<div className={styles.content}>{content()}</div>
</div>
<div className={styles.chatAvatar}>{props.from?.name[0]}</div>
</div>
) : (
<div className={styles.chatLeft}>
<div className={styles.chatAvatar}>
<img src={props.to?.cust_info.avatar} alt="" />
</div>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.to?.cust_info.name}</div>
<div className={styles.content}>{content()}</div>
</div>
</div>
)}
</>
);
return <>{content()}</>;
};

View File

@@ -1,50 +1,29 @@
import { IChatItem } from '../ChatLogsType';
import styles from './index.module.scss';
export const ChatMeetingVoiceCall: React.FC<IChatItem> = (props) => {
function content() {
try {
const msg = JSON.parse(props.chat?.content as string);
// todo console.log(msg);
return (
<a
style={{ display: 'flex', color: '#000' }}
download={msg.file_name}
href={`/api/${msg.path}`}
>
<div style={{ wordBreak: 'break-all', paddingRight: 8 }}>// TODO 音频存档</div>
</a>
);
} catch (_e) {
return (
<div>
<div style={{ wordBreak: 'break-all', paddingRight: 8 }}>{props.chat?.content}</div>
</div>
<audio
controls
src={`/api/${msg.path}`}
onPlay={(e) => {
const audios = document.querySelectorAll('audio');
if (audios) {
audios.forEach((el) => {
if (el != e.target) {
el.pause();
}
});
}
}}
></audio>
);
} catch (e) {
return <div style={{ wordBreak: 'break-all' }}>{props.chat?.content}</div>;
}
}
return (
<>
{props.from?.user_id == props.chat?.msg_from ? (
<div className={styles.chatRight}>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.from?.name}</div>
<div className={styles.content}>{content()}</div>
</div>
<div className={styles.chatAvatar}>{props.from?.name[0]}</div>
</div>
) : (
<div className={styles.chatLeft}>
<div className={styles.chatAvatar}>
<img src={props.to?.cust_info.avatar} alt="" />
</div>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.to?.cust_info.name}</div>
<div className={styles.content}>{content()}</div>
</div>
</div>
)}
</>
);
return <>{content()}</>;
};

View File

@@ -1,17 +1,26 @@
import { Modal } from 'antd';
import { useEffect, useState } from 'react';
import { IChatItem } from '../ChatLogsType';
import styles from './index.module.scss';
export const ChatRecord: React.FC<IChatItem> = (props) => {
const [visible, setVisible] = useState(false);
function chatRecordContent(data: any) {
// todo console.log(msg);
function chatRecordContent(data: any, type: string) {
if (data.type == 'ChatRecordText') {
const content = JSON.parse(data.content);
return <div>{content.content}</div>;
return (
<div
style={{
maxWidth: type == 'ellipsis' ? 400 : 'inherit',
whiteSpace: type == 'ellipsis' ? 'nowrap' : 'normal',
minWidth: '0',
overflow: type == 'ellipsis' ? 'hidden' : '',
textOverflow: type == 'ellipsis' ? 'ellipsis' : 'inherit',
}}
>
{content.content}
</div>
);
} else if (data.type == 'ChatRecordImage') {
return <div>[]</div>;
} else if (data.type == 'ChatRecordFile') {
@@ -40,8 +49,7 @@ export const ChatRecord: React.FC<IChatItem> = (props) => {
function content() {
try {
const msg = JSON.parse(props.chat?.content as string);
// setRecord(msg);
console.log(msg);
// console.log(msg);
return (
<div
style={{
@@ -57,13 +65,13 @@ export const ChatRecord: React.FC<IChatItem> = (props) => {
>
<div style={{ wordBreak: 'break-all', fontSize: 16 }}>{msg.title}</div>
{msg.item[0] ? (
<div style={{ color: '#999' }}>{chatRecordContent(msg.item[0])}</div>
<div style={{ color: '#999' }}>{chatRecordContent(msg.item[0], 'ellipsis')}</div>
) : null}
{msg.item[1] ? (
<div style={{ color: '#999' }}>{chatRecordContent(msg.item[1])}</div>
<div style={{ color: '#999' }}>{chatRecordContent(msg.item[1], 'ellipsis')}</div>
) : null}
{msg.item[2] ? (
<div style={{ color: '#999' }}>{chatRecordContent(msg.item[2])}</div>
<div style={{ color: '#999' }}>{chatRecordContent(msg.item[2], 'ellipsis')}</div>
) : null}
<div style={{ borderTop: '1px solid #ddd', color: '#999', marginTop: 8, paddingTop: 8 }}>
@@ -93,13 +101,12 @@ export const ChatRecord: React.FC<IChatItem> = (props) => {
{record ? (
<div>
{record.item.map((item: any) => {
console.log(item);
return (
<div
style={{ padding: '8px 0', borderBottom: '1px solid #eee' }}
key={`${item.msgtime}_${item.type}_${item.content}`}
>
{chatRecordContent(item)}
{chatRecordContent(item, 'no_ellipsis')}
</div>
);
})}
@@ -107,25 +114,7 @@ export const ChatRecord: React.FC<IChatItem> = (props) => {
) : null}
</div>
</Modal>
{props.from?.user_id == props.chat?.msg_from ? (
<div className={styles.chatRight}>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.from?.name}</div>
<div className={styles.content}>{content()}</div>
</div>
<div className={styles.chatAvatar}>{props.from?.name[0]}</div>
</div>
) : (
<div className={styles.chatLeft}>
<div className={styles.chatAvatar}>
<img src={props.to?.cust_info.avatar} alt="" />
</div>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.to?.cust_info.name}</div>
<div className={styles.content}>{content()}</div>
</div>
</div>
)}
{content()}
</>
);
};

View File

@@ -1,8 +1,12 @@
import { RedEnvelopeFilled } from '@ant-design/icons';
import { IChatItem } from '../ChatLogsType';
import styles from './index.module.scss';
export const ChatRedpacket: React.FC<IChatItem> = (props) => {
const type: any = {
1: '普通红包',
2: '拼手气群红包',
3: '激励群红包',
};
function content() {
try {
const msg = JSON.parse(props.chat?.content as string);
@@ -19,7 +23,9 @@ export const ChatRedpacket: React.FC<IChatItem> = (props) => {
</div>
</div>
</div>
<div style={{ borderTop: '1px solid #ddd', marginTop: 12 }}></div>
<div style={{ borderTop: '1px solid #ddd', marginTop: 8, paddingTop: 8, color: '#999' }}>
{type[msg.type]}
</div>
</div>
);
} catch (_e) {
@@ -31,33 +37,13 @@ export const ChatRedpacket: React.FC<IChatItem> = (props) => {
/>
<div style={{ wordBreak: 'break-all' }}>{props.chat?.content}</div>
</div>
<div style={{ borderTop: '1px solid #ddd', marginTop: 12 }}></div>
<div style={{ borderTop: '1px solid #ddd', marginTop: 8, paddingTop: 8, color: '#999' }}>
</div>
</div>
);
}
}
return (
<>
{props.from?.user_id == props.chat?.msg_from ? (
<div className={styles.chatRight}>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.from?.name}</div>
<div className={styles.content}>{content()}</div>
</div>
<div className={styles.chatAvatar}>{props.from?.name[0]}</div>
</div>
) : (
<div className={styles.chatLeft}>
<div className={styles.chatAvatar}>
<img src={props.to?.cust_info.avatar} alt="" />
</div>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.to?.cust_info.name}</div>
<div className={styles.content}>{content()}</div>
</div>
</div>
)}
</>
);
return <>{content()}</>;
};

View File

@@ -1,28 +1,5 @@
import { IChatItem } from '../ChatLogsType';
import styles from './index.module.scss';
export const ChatText: React.FC<IChatItem> = (props) => {
return (
<div>
{props.from?.user_id == props.chat?.msg_from ? (
<div className={styles.chatRight}>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.from?.name}</div>
<div className={styles.content}>{props.chat?.content}</div>
</div>
<div className={styles.chatAvatar}>{props.from?.name[0]}</div>
</div>
) : (
<div className={styles.chatLeft}>
<div className={styles.chatAvatar}>
<img src={props.to?.cust_info.avatar} alt="" />
</div>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.to?.cust_info.name}</div>
<div className={styles.content}>{props.chat?.content}</div>
</div>
</div>
)}
</div>
);
return <>{props.chat?.content}</>;
};

View File

@@ -66,7 +66,7 @@ export const ChatTime: React.FC<IChatTimeProps> = (props) => {
padding: '0 8px',
borderRadius: 4,
lineHeight: 1,
height: 26,
height: 24,
display: 'inline-flex',
justifyContent: 'center',
alignItems: 'center',

View File

@@ -0,0 +1,17 @@
import { IChatItem } from '../ChatLogsType';
export const ChatTodo: React.FC<IChatItem> = (props) => {
function content() {
return (
<div style={{ display: 'flex', color: '#000', flexDirection: 'column' }}>
<div style={{ wordBreak: 'break-all' }}>{props.chat?.title}</div>
<div style={{ wordBreak: 'break-all' }}>{props.chat?.content}</div>
<div style={{ borderTop: '1px solid #ddd', color: '#999', marginTop: 8, paddingTop: 8 }}>
</div>
</div>
);
}
return <>{content()}</>;
};

View File

@@ -29,6 +29,12 @@ export const ChatVideo: React.FC<IChatItem> = (props) => {
className={styles.video}
onClick={() => {
setOpen(true);
const audios = document.querySelectorAll('audio');
if (audios) {
audios.forEach((el) => {
el.pause();
});
}
setTimeout(() => {
videoRef.current.play().catch((error) => {
console.log(error);
@@ -89,27 +95,5 @@ export const ChatVideo: React.FC<IChatItem> = (props) => {
}
}
return (
<>
{props.from?.user_id == props.chat?.msg_from ? (
<div className={styles.chatRight}>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.from?.name}</div>
<div className={styles.content}>{content()}</div>
</div>
<div className={styles.chatAvatar}>{props.from?.name[0]}</div>
</div>
) : (
<div className={styles.chatLeft}>
<div className={styles.chatAvatar}>
<img src={props.to?.cust_info.avatar} alt="" />
</div>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.to?.cust_info.name}</div>
<div className={styles.content}>{content()}</div>
</div>
</div>
)}
</>
);
return <>{content()}</>;
};

View File

@@ -1,11 +1,18 @@
import { FileTextFilled } from '@ant-design/icons';
import { useRef, useState } from 'react';
import { IChatItem } from '../ChatLogsType';
import styles from './index.module.scss';
export const ChatVoice: React.FC<IChatItem> = (props) => {
const [open, setOpen] = useState(false);
const audioRef = useRef<any>();
function readBlob(blob: Blob, callback: Function) {
const reader = new FileReader();
reader.onload = function (e) {
const data = new Uint8Array(e.target.result);
callback(data);
};
reader.readAsArrayBuffer(blob);
}
function content() {
try {
@@ -19,7 +26,7 @@ export const ChatVoice: React.FC<IChatItem> = (props) => {
color: '#000',
justifyContent: 'flex-end',
alignItems: 'center',
marginBottom: 4,
cursor: 'pointer',
}}
onClick={() => {
const audios = document.querySelectorAll('audio');
@@ -28,10 +35,28 @@ export const ChatVoice: React.FC<IChatItem> = (props) => {
el.pause();
});
}
audioRef.current.play().catch((error: any) => {
console.log(error);
});
setOpen(true);
if (!open) {
fetch(`/api/${msg.path}`)
.then((response) => response.blob())
.then((res) => {
let blob = new Blob([res]);
readBlob(blob, function (data: any) {
if (window.AMR) {
var buffer = window.AMR.toWAV(data);
var url = URL.createObjectURL(new Blob([buffer], { type: 'audio/x-wav' }));
audioRef.current.src = url;
audioRef.current.play().catch((err: any) => {
console.log(err);
});
}
});
});
setOpen(true);
} else {
audioRef.current.play().catch((err: any) => {
console.log(err);
});
}
}}
>
<span style={{ lineHeight: 1, marginRight: 4, minWidth: 100, textAlign: 'right' }}>
@@ -45,10 +70,9 @@ export const ChatVoice: React.FC<IChatItem> = (props) => {
</svg>
</div>
<audio
ref={audioRef}
src={`/api/${msg.path}`}
style={{ display: `${open ? 'block' : 'none'}` }}
controls
style={{ display: open ? 'block' : 'none', marginTop: 8 }}
ref={audioRef}
></audio>
</div>
);
@@ -62,27 +86,5 @@ export const ChatVoice: React.FC<IChatItem> = (props) => {
}
}
return (
<>
{props.from?.user_id == props.chat?.msg_from ? (
<div className={styles.chatRight}>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.from?.name}</div>
<div className={styles.content}>{content()}</div>
</div>
<div className={styles.chatAvatar}>{props.from?.name[0]}</div>
</div>
) : (
<div className={styles.chatLeft}>
<div className={styles.chatAvatar}>
<img src={props.to?.cust_info.avatar} alt="" />
</div>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.to?.cust_info.name}</div>
<div className={styles.content}>{content()}</div>
</div>
</div>
)}
</>
);
return <>{content()}</>;
};

View File

@@ -1,18 +1,25 @@
import { durationFormat } from '@/services/utils';
import { IChatItem } from '../ChatLogsType';
import styles from './index.module.scss';
export const ChatVoiptext: React.FC<IChatItem> = (props) => {
const invitetype: any = {
'1': '单人视频通话',
'2': '单人语音通话',
'3': '多人视频通话',
'4': '多人语音通话',
};
function content() {
try {
// todo ///
const msg = JSON.parse(props.chat?.content as string);
// console.log(msg);
return (
<div style={{ display: 'flex', color: '#000' }}>
<div style={{ display: 'flex', color: '#000', flexDirection: 'column' }}>
<div style={{ wordBreak: 'break-all', paddingRight: 8 }}>
{durationFormat(msg.callduration)}
</div>
<div style={{ borderTop: '1px solid #ddd', marginTop: 8, paddingTop: 8, color: '#999' }}>
{invitetype[msg.invitetype]}
</div>
</div>
);
} catch (_e) {
@@ -24,27 +31,5 @@ export const ChatVoiptext: React.FC<IChatItem> = (props) => {
}
}
return (
<>
{props.from?.user_id == props.chat?.msg_from ? (
<div className={styles.chatRight}>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.from?.name}</div>
<div className={styles.content}>{content()}</div>
</div>
<div className={styles.chatAvatar}>{props.from?.name[0]}</div>
</div>
) : (
<div className={styles.chatLeft}>
<div className={styles.chatAvatar}>
<img src={props.to?.cust_info.avatar} alt="" />
</div>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.to?.cust_info.name}</div>
<div className={styles.content}>{content()}</div>
</div>
</div>
)}
</>
);
return <>{content()}</>;
};

View File

@@ -0,0 +1,19 @@
import { IChatItem } from '../ChatLogsType';
export const ChatVote: React.FC<IChatItem> = (props) => {
const votetype: any = { 101: '发起投票', 102: '参与投票' };
function content() {
return (
<div style={{ display: 'flex', color: '#000', flexDirection: 'column' }}>
<div style={{ wordBreak: 'break-all' }}>{props.chat?.votetitle}</div>
<div style={{ wordBreak: 'break-all' }}>{props.chat?.voteitem}</div>
<div style={{ borderTop: '1px solid #ddd', color: '#999', marginTop: 8, paddingTop: 8 }}>
[{votetype[props.chat?.votetype as string]}]
</div>
</div>
);
}
return <>{content()}</>;
};

View File

@@ -1,54 +1,33 @@
import { FileTextFilled } from '@ant-design/icons';
import { IChatItem } from '../ChatLogsType';
import styles from './index.module.scss';
export const ChatWeapp: React.FC<IChatItem> = (props) => {
function content() {
try {
const msg = JSON.parse(props.chat?.content as string);
console.log(msg);
// console.log(msg);
return (
<a
style={{ display: 'flex', color: '#000' }}
download={msg.file_name}
href={`/api/${msg.path}`}
>
<div style={{ wordBreak: 'break-all', paddingRight: 8 }}>{msg.file_name}</div>
<FileTextFilled style={{ fontSize: 40, color: '#FA9D3B', flexShrink: 0 }} />
</a>
<div style={{ display: 'flex', color: '#000' }}>
<svg viewBox="0 0 1024 1024" width="40" height="40">
<path d="M512 0a512 512 0 1 0 512 512A512 512 0 0 0 512 0z m256.717 460.186a151.962 151.962 0 0 1-87.347 65.74 83.251 83.251 0 0 1-24.474 4.096 29.082 29.082 0 0 1 0-58.163 15.667 15.667 0 0 0 6.451-1.229 91.443 91.443 0 0 0 55.91-40.96 75.264 75.264 0 0 0 11.06-39.628c0-45.978-42.496-83.866-94.31-83.866a105.267 105.267 0 0 0-51.2 13.414 81.92 81.92 0 0 0-43.725 70.452v244.224a138.445 138.445 0 0 1-72.704 120.422 159.642 159.642 0 0 1-79.77 20.48c-84.378 0-153.6-63.488-153.6-142.029a136.192 136.192 0 0 1 19.763-69.837 151.962 151.962 0 0 1 87.347-65.74 85.914 85.914 0 0 1 24.474-4.096 29.082 29.082 0 1 1 0 58.163 15.667 15.667 0 0 0-6.451 1.229 95.949 95.949 0 0 0-55.91 40.96 75.264 75.264 0 0 0-11.06 39.628c0 45.978 42.496 83.866 94.925 83.866a105.267 105.267 0 0 0 51.2-13.414 81.92 81.92 0 0 0 43.622-70.452V390.35a138.752 138.752 0 0 1 72.807-120.525 151.245 151.245 0 0 1 79.155-21.504c84.378 0 153.6 63.488 153.6 142.029a136.192 136.192 0 0 1-19.763 69.837z"></path>
</svg>
<div style={{ wordBreak: 'break-all', paddingLeft: 12, minWidth: 100 }}>
<div>{msg.title}</div>
<div>{msg.description}</div>
</div>
</div>
);
} catch (_e) {
return (
<div>
<div style={{ wordBreak: 'break-all', paddingRight: 8 }}>{props.chat?.content}</div>
<FileTextFilled style={{ fontSize: 40, color: '#FA9D3B', flexShrink: 0 }} />
<svg viewBox="0 0 1024 1024" width="40" height="40">
<path d="M512 0a512 512 0 1 0 512 512A512 512 0 0 0 512 0z m256.717 460.186a151.962 151.962 0 0 1-87.347 65.74 83.251 83.251 0 0 1-24.474 4.096 29.082 29.082 0 0 1 0-58.163 15.667 15.667 0 0 0 6.451-1.229 91.443 91.443 0 0 0 55.91-40.96 75.264 75.264 0 0 0 11.06-39.628c0-45.978-42.496-83.866-94.31-83.866a105.267 105.267 0 0 0-51.2 13.414 81.92 81.92 0 0 0-43.725 70.452v244.224a138.445 138.445 0 0 1-72.704 120.422 159.642 159.642 0 0 1-79.77 20.48c-84.378 0-153.6-63.488-153.6-142.029a136.192 136.192 0 0 1 19.763-69.837 151.962 151.962 0 0 1 87.347-65.74 85.914 85.914 0 0 1 24.474-4.096 29.082 29.082 0 1 1 0 58.163 15.667 15.667 0 0 0-6.451 1.229 95.949 95.949 0 0 0-55.91 40.96 75.264 75.264 0 0 0-11.06 39.628c0 45.978 42.496 83.866 94.925 83.866a105.267 105.267 0 0 0 51.2-13.414 81.92 81.92 0 0 0 43.622-70.452V390.35a138.752 138.752 0 0 1 72.807-120.525 151.245 151.245 0 0 1 79.155-21.504c84.378 0 153.6 63.488 153.6 142.029a136.192 136.192 0 0 1-19.763 69.837z"></path>
</svg>
<div style={{ wordBreak: 'break-all', paddingLeft: 12 }}>{props.chat?.content}</div>
</div>
);
}
}
return (
<>
{props.from?.user_id == props.chat?.msg_from ? (
<div className={styles.chatRight}>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.from?.name}</div>
<div className={styles.content}>{content()}</div>
</div>
<div className={styles.chatAvatar}>{props.from?.name[0]}</div>
</div>
) : (
<div className={styles.chatLeft}>
<div className={styles.chatAvatar}>
<img src={props.to?.cust_info.avatar} alt="" />
</div>
<div className={styles.chatContentBox}>
<div className={styles.name}>{props.to?.cust_info.name}</div>
<div className={styles.content}>{content()}</div>
</div>
</div>
)}
</>
);
return <>{content()}</>;
};

View File

@@ -12,21 +12,26 @@
}
.chatAvatar {
display: flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
width: 34px;
height: 34px;
background-color: #69b1ff;
border-radius: 4px;
img {
max-width: 100%;
max-height: 100%;
object-fit: cover;
background-color: #fff;
border-radius: 2px;
border-radius: 4px;
}
}
.name {
margin-bottom: 8px;
margin-bottom: 4px;
color: #999;
}
@@ -34,10 +39,12 @@
position: relative;
display: flex;
justify-content: center;
min-height: 40px;
padding: 12px;
word-break: break-all;
background-color: #fff;
border-radius: 4px;
flex-direction: column;
&::before {
position: absolute;
@@ -58,7 +65,7 @@
.chatRight {
display: flex;
justify-content: end;
justify-content: flex-end;
margin-bottom: 12px;
.name {
@@ -69,7 +76,7 @@
display: inline-flex;
flex-direction: column;
flex-shrink: 0;
justify-content: end;
justify-content: flex-end;
max-width: 60%;
margin-right: 16px;
}
@@ -112,7 +119,14 @@
.imgPreview {
& > div {
display: flex;
justify-content: center;
align-items: center;
justify-content: center;
}
}
.revokeMsg{
background-color: #8c8c8c;
color: #fff;
border-radius: 4px;
padding: 0 12px;
}