开发: 聊天页面修改
This commit is contained in:
@@ -6,12 +6,15 @@ import { ChatFile } from './ChatFile';
|
|||||||
import { ChatImage } from './ChatImage';
|
import { ChatImage } from './ChatImage';
|
||||||
import { ChatLink } from './ChatLink';
|
import { ChatLink } from './ChatLink';
|
||||||
import { ChatLocation } from './ChatLocation';
|
import { ChatLocation } from './ChatLocation';
|
||||||
|
import { ChatMeetingVoiceCall } from './ChatMeetingVoiceCall';
|
||||||
import { ChatRecord } from './ChatRecord';
|
import { ChatRecord } from './ChatRecord';
|
||||||
import { ChatRedpacket } from './ChatRedpacket';
|
import { ChatRedpacket } from './ChatRedpacket';
|
||||||
import { ChatRevoke } from './ChatRevoke';
|
import { ChatRevoke } from './ChatRevoke';
|
||||||
import { ChatText } from './ChatText';
|
import { ChatText } from './ChatText';
|
||||||
import { ChatVideo } from './ChatVideo';
|
import { ChatVideo } from './ChatVideo';
|
||||||
import { ChatVoice } from './ChatVoice';
|
import { ChatVoice } from './ChatVoice';
|
||||||
|
import { ChatVoiptext } from './ChatVoiptext';
|
||||||
|
import { ChatWeapp } from './ChatWeapp';
|
||||||
|
|
||||||
export const ChatBar: React.FC<IChatItem> = (props) => {
|
export const ChatBar: React.FC<IChatItem> = (props) => {
|
||||||
const { from, to, chat } = props;
|
const { from, to, chat } = props;
|
||||||
@@ -37,6 +40,12 @@ export const ChatBar: React.FC<IChatItem> = (props) => {
|
|||||||
return <ChatVoice from={from} to={to} chat={chat}></ChatVoice>;
|
return <ChatVoice from={from} to={to} chat={chat}></ChatVoice>;
|
||||||
} else if (chat?.msg_type == 'chatrecord') {
|
} else if (chat?.msg_type == 'chatrecord') {
|
||||||
return <ChatRecord from={from} to={to} chat={chat}></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') {
|
} else if (chat?.msg_type == 'revoke') {
|
||||||
return <ChatRevoke></ChatRevoke>;
|
return <ChatRevoke></ChatRevoke>;
|
||||||
} else if (chat?.msg_type == 'agree' || chat?.msg_type == 'disagree') {
|
} else if (chat?.msg_type == 'agree' || chat?.msg_type == 'disagree') {
|
||||||
|
@@ -1,15 +1,18 @@
|
|||||||
import React from 'react';
|
import { Image } from 'antd';
|
||||||
|
import React, { useState } from 'react';
|
||||||
import { IChatItem } from '../ChatLogsType';
|
import { IChatItem } from '../ChatLogsType';
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
// 表情
|
// 表情
|
||||||
export const ChatEmotion: React.FC<IChatItem> = (props) => {
|
export const ChatEmotion: React.FC<IChatItem> = (props) => {
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
function content() {
|
function content() {
|
||||||
try {
|
try {
|
||||||
const msg = JSON.parse(props.chat?.content as string);
|
const msg = JSON.parse(props.chat?.content as string);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
className={styles.imgPreview}
|
||||||
style={{
|
style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
color: '#000',
|
color: '#000',
|
||||||
@@ -18,7 +21,13 @@ export const ChatEmotion: React.FC<IChatItem> = (props) => {
|
|||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img
|
<Image
|
||||||
|
preview={{
|
||||||
|
visible: visible,
|
||||||
|
onVisibleChange: (value) => {
|
||||||
|
setVisible(value);
|
||||||
|
},
|
||||||
|
}}
|
||||||
src={`/api/${msg.path}`}
|
src={`/api/${msg.path}`}
|
||||||
style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }}
|
style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }}
|
||||||
alt=""
|
alt=""
|
||||||
|
@@ -1,13 +1,17 @@
|
|||||||
|
import { Image } from 'antd';
|
||||||
|
import { useState } from 'react';
|
||||||
import { IChatItem } from '../ChatLogsType';
|
import { IChatItem } from '../ChatLogsType';
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
export const ChatImage: React.FC<IChatItem> = (props) => {
|
export const ChatImage: React.FC<IChatItem> = (props) => {
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
function content() {
|
function content() {
|
||||||
try {
|
try {
|
||||||
const msg = JSON.parse(props.chat?.content as string);
|
const msg = JSON.parse(props.chat?.content as string);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
className={styles.imgPreview}
|
||||||
style={{
|
style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
color: '#000',
|
color: '#000',
|
||||||
@@ -16,7 +20,13 @@ export const ChatImage: React.FC<IChatItem> = (props) => {
|
|||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img
|
<Image
|
||||||
|
preview={{
|
||||||
|
visible: visible,
|
||||||
|
onVisibleChange: (value, prevValue, currentIndex) => {
|
||||||
|
setVisible(value);
|
||||||
|
},
|
||||||
|
}}
|
||||||
src={`/api/${msg.path}`}
|
src={`/api/${msg.path}`}
|
||||||
style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }}
|
style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }}
|
||||||
alt=""
|
alt=""
|
||||||
|
50
src/pages/ChatLogs/components/ChatMeetingVoiceCall.tsx
Normal file
50
src/pages/ChatLogs/components/ChatMeetingVoiceCall.tsx
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
@@ -1,26 +1,79 @@
|
|||||||
import { FileTextFilled } from '@ant-design/icons';
|
import { Modal } from 'antd';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
import { IChatItem } from '../ChatLogsType';
|
import { IChatItem } from '../ChatLogsType';
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
export const ChatRecord: React.FC<IChatItem> = (props) => {
|
export const ChatRecord: React.FC<IChatItem> = (props) => {
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
|
||||||
|
function chatRecordContent(data: any) {
|
||||||
|
// todo console.log(msg);
|
||||||
|
|
||||||
|
if (data.type == 'ChatRecordText') {
|
||||||
|
const content = JSON.parse(data.content);
|
||||||
|
return <div>{content.content}</div>;
|
||||||
|
} else if (data.type == 'ChatRecordImage') {
|
||||||
|
return <div>[图片]</div>;
|
||||||
|
} else if (data.type == 'ChatRecordFile') {
|
||||||
|
return <div>[文件]</div>;
|
||||||
|
} else if (data.type == 'ChatRecordVideo') {
|
||||||
|
return <div>[视频]</div>;
|
||||||
|
} else if (data.type == 'ChatRecordLink') {
|
||||||
|
return <div>[链接]</div>;
|
||||||
|
} else if (data.type == 'ChatRecordLocation') {
|
||||||
|
return <div>[位置]</div>;
|
||||||
|
} else if (data.type == 'ChatRecordMixed') {
|
||||||
|
return <div>[混合信息]</div>;
|
||||||
|
}
|
||||||
|
return <div>[未匹配到类型信息]</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [record, setRecord] = useState<any>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
try {
|
||||||
|
const msg = JSON.parse(props.chat?.content as string);
|
||||||
|
setRecord(msg);
|
||||||
|
} catch (e) {}
|
||||||
|
}, [props.chat]);
|
||||||
|
|
||||||
function content() {
|
function content() {
|
||||||
try {
|
try {
|
||||||
const msg = JSON.parse(props.chat?.content as string);
|
const msg = JSON.parse(props.chat?.content as string);
|
||||||
|
// setRecord(msg);
|
||||||
|
console.log(msg);
|
||||||
return (
|
return (
|
||||||
<a
|
<div
|
||||||
style={{ display: 'flex', color: '#000' }}
|
style={{
|
||||||
download={msg.file_name}
|
display: 'flex',
|
||||||
href={`/api/${msg.path}`}
|
color: '#000',
|
||||||
|
flexDirection: 'column',
|
||||||
|
minWidth: 260,
|
||||||
|
cursor: 'pointer',
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setVisible(true);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ wordBreak: 'break-all', paddingRight: 8 }}>{msg.file_name}</div>
|
<div style={{ wordBreak: 'break-all', fontSize: 16 }}>{msg.title}</div>
|
||||||
<FileTextFilled style={{ fontSize: 40, color: '#FA9D3B', flexShrink: 0 }} />
|
{msg.item[0] ? (
|
||||||
</a>
|
<div style={{ color: '#999' }}>{chatRecordContent(msg.item[0])}</div>
|
||||||
|
) : null}
|
||||||
|
{msg.item[1] ? (
|
||||||
|
<div style={{ color: '#999' }}>{chatRecordContent(msg.item[1])}</div>
|
||||||
|
) : null}
|
||||||
|
{msg.item[2] ? (
|
||||||
|
<div style={{ color: '#999' }}>{chatRecordContent(msg.item[2])}</div>
|
||||||
|
) : null}
|
||||||
|
<div style={{ borderTop: '1px solid #ddd', color: '#999', marginTop: 8, paddingTop: 8 }}>
|
||||||
|
聊天记录
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
} catch (_e) {
|
} catch (_e) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div style={{ wordBreak: 'break-all', paddingRight: 8 }}>{props.chat?.content}</div>
|
<div style={{ wordBreak: 'break-all', paddingRight: 8 }}>{props.chat?.content}</div>
|
||||||
<FileTextFilled style={{ fontSize: 40, color: '#FA9D3B', flexShrink: 0 }} />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -28,6 +81,32 @@ export const ChatRecord: React.FC<IChatItem> = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<Modal
|
||||||
|
open={visible}
|
||||||
|
footer={false}
|
||||||
|
title={record ? record.title : '无标题'}
|
||||||
|
onCancel={() => {
|
||||||
|
setVisible(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
{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}`}
|
||||||
|
>
|
||||||
|
{chatRecordContent(item)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
{props.from?.user_id == props.chat?.msg_from ? (
|
{props.from?.user_id == props.chat?.msg_from ? (
|
||||||
<div className={styles.chatRight}>
|
<div className={styles.chatRight}>
|
||||||
<div className={styles.chatContentBox}>
|
<div className={styles.chatContentBox}>
|
||||||
|
@@ -16,9 +16,9 @@ export const ChatTime: React.FC<IChatTimeProps> = (props) => {
|
|||||||
const yesterday = new Date();
|
const yesterday = new Date();
|
||||||
yesterday.setDate(yesterday.getDate() - 1);
|
yesterday.setDate(yesterday.getDate() - 1);
|
||||||
const dayDiff =
|
const dayDiff =
|
||||||
(Date.parse(
|
(new Date(
|
||||||
`${now.getFullYear()}-${padWith(now.getMonth() + 1)}-${padWith(now.getDate())} 00:00:00`,
|
`${now.getFullYear()}-${padWith(now.getMonth() + 1)}-${padWith(now.getDate())} 00:00:00`,
|
||||||
) -
|
).getTime() -
|
||||||
new Date(props.msgtime).getTime()) /
|
new Date(props.msgtime).getTime()) /
|
||||||
(24 * 60 * 60 * 1000) +
|
(24 * 60 * 60 * 1000) +
|
||||||
1;
|
1;
|
||||||
@@ -58,7 +58,7 @@ export const ChatTime: React.FC<IChatTimeProps> = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex', justifyContent: 'center' }}>
|
<div style={{ display: 'flex', justifyContent: 'center', marginBottom: 12 }}>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
background: '#DADADA',
|
background: '#DADADA',
|
||||||
|
@@ -1,8 +1,13 @@
|
|||||||
import { PlayCircleOutlined } from '@ant-design/icons';
|
import { CloseOutlined, PlayCircleOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
|
import { useRef, useState } from 'react';
|
||||||
import { IChatItem } from '../ChatLogsType';
|
import { IChatItem } from '../ChatLogsType';
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
export const ChatVideo: React.FC<IChatItem> = (props) => {
|
export const ChatVideo: React.FC<IChatItem> = (props) => {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const videoRef = useRef<any>();
|
||||||
|
|
||||||
function playLen(v: number) {
|
function playLen(v: number) {
|
||||||
const len = Number(v) || 0;
|
const len = Number(v) || 0;
|
||||||
if (len > 60) {
|
if (len > 60) {
|
||||||
@@ -19,10 +24,58 @@ export const ChatVideo: React.FC<IChatItem> = (props) => {
|
|||||||
const msg = JSON.parse(props.chat?.content as string);
|
const msg = JSON.parse(props.chat?.content as string);
|
||||||
// console.log(msg);
|
// console.log(msg);
|
||||||
return (
|
return (
|
||||||
<a className={styles.video} href={`/api/${msg.path}`} target="_blank">
|
<>
|
||||||
<PlayCircleOutlined style={{ color: '#fff', fontSize: 40 }} />
|
<div
|
||||||
<span className={styles.videoTime}>{playLen(msg.play_length)}</span>
|
className={styles.video}
|
||||||
</a>
|
onClick={() => {
|
||||||
|
setOpen(true);
|
||||||
|
videoRef.current.play().catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PlayCircleOutlined style={{ color: '#fff', fontSize: 40 }} />
|
||||||
|
<span className={styles.videoTime}>{playLen(msg.play_length)}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: 'fixed',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
width: '100vw',
|
||||||
|
height: '100vh',
|
||||||
|
background: 'rgba(0 ,0, 0, 0.45)',
|
||||||
|
zIndex: 1000,
|
||||||
|
display: open ? 'flex' : 'none',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
}}
|
||||||
|
onClick={(e) => {
|
||||||
|
setOpen(false);
|
||||||
|
videoRef.current.pause();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CloseOutlined
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: 12,
|
||||||
|
right: 12,
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 26,
|
||||||
|
cursor: 'pointer',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<video
|
||||||
|
ref={videoRef}
|
||||||
|
style={{ maxWidth: '100%', maxHeight: '100%' }}
|
||||||
|
src={`/api/${msg.path}`}
|
||||||
|
controls
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
></video>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
} catch (_e) {
|
} catch (_e) {
|
||||||
return (
|
return (
|
||||||
|
@@ -1,24 +1,56 @@
|
|||||||
import { FileTextFilled } from '@ant-design/icons';
|
import { FileTextFilled } from '@ant-design/icons';
|
||||||
|
import { useRef, useState } from 'react';
|
||||||
import { IChatItem } from '../ChatLogsType';
|
import { IChatItem } from '../ChatLogsType';
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
export const ChatVoice: React.FC<IChatItem> = (props) => {
|
export const ChatVoice: React.FC<IChatItem> = (props) => {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const audioRef = useRef<any>();
|
||||||
|
|
||||||
function content() {
|
function content() {
|
||||||
try {
|
try {
|
||||||
const msg = JSON.parse(props.chat?.content as string);
|
const msg = JSON.parse(props.chat?.content as string);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<a style={{ display: 'flex', color: '#000' }} href={`/api/${msg.path}`} target="_blank">
|
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
<span style={{ lineHeight: 1, marginRight: 4, minWidth: 100, textAlign: 'right' }}>
|
<div
|
||||||
{msg.play_length}"
|
style={{
|
||||||
</span>
|
display: 'flex',
|
||||||
<svg viewBox="0 0 1024 1024" width="18" height="18">
|
color: '#000',
|
||||||
<path
|
justifyContent: 'flex-end',
|
||||||
d="M913.568627 518.334145C913.568627 483.422393 894.958532 451.162604 864.748584 433.706729 834.538616 416.250852 797.318425 416.250852 767.108477 433.706729 736.89851 451.162604 718.288414 483.422393 718.288414 518.334145 718.288414 553.245895 736.89851 585.505684 767.108477 602.961559 797.318425 620.417436 834.538616 620.417436 864.748584 602.961559 894.958532 585.505684 913.568627 553.245895 913.568627 518.334145L913.568627 518.334145ZM581.566143 215.288946C581.566143 215.288946 593.269057 203.098427 620.669932 203.098427 650.6546 203.098427 674.950626 227.414165 674.950626 257.423171 674.950626 290.452615 648.917554 305.250663 636.758739 309.031723 568.451875 353.599725 523.116685 430.436655 523.116685 518.116824 523.116685 605.970743 568.603889 682.938067 637.149606 727.440872 650.915177 731.852057 674.950626 743.064634 674.950626 778.940765 674.950626 808.949772 650.6546 833.265507 620.669932 833.265507 593.269057 833.265507 581.566143 821.07499 581.566143 821.07499 481.233659 757.536806 414.403283 645.801687 414.403283 518.181916 414.403283 390.562145 481.233659 278.805502 581.566143 215.288946L581.566143 215.288946ZM348.376225 14.135304C348.376225 14.135304 365.941399 7.529394 392.690949 7.529394 428.668185 7.529394 457.82781 36.73442 457.82781 72.719107 457.82781 98.186537 406.282822 128.195544 388.54391 137.474179 297.265513 229.695819 240.704994 356.381112 240.704994 496.452082 240.704994 650.321426 309.055287 787.849957 416.661363 881.418878 440.740242 890.980031 457.82781 914.426591 457.82781 941.914889 457.82781 977.899576 428.668185 1007.104602 392.690949 1007.104602 363.314276 1007.104602 345.336511 998.13011 345.336511 998.13011 202.12236 882.635664 110.431373 705.732666 110.431373 507.316947 110.431373 307.532423 203.446734 129.564556 348.376225 14.135304L348.376225 14.135304Z"
|
alignItems: 'center',
|
||||||
fill="#000000"
|
marginBottom: 4,
|
||||||
></path>
|
}}
|
||||||
</svg>
|
onClick={() => {
|
||||||
</a>
|
const audios = document.querySelectorAll('audio');
|
||||||
|
if (audios) {
|
||||||
|
audios.forEach((el) => {
|
||||||
|
el.pause();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
audioRef.current.play().catch((error: any) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
setOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span style={{ lineHeight: 1, marginRight: 4, minWidth: 100, textAlign: 'right' }}>
|
||||||
|
{msg.play_length}"
|
||||||
|
</span>
|
||||||
|
<svg viewBox="0 0 1024 1024" width="18" height="18">
|
||||||
|
<path
|
||||||
|
d="M913.568627 518.334145C913.568627 483.422393 894.958532 451.162604 864.748584 433.706729 834.538616 416.250852 797.318425 416.250852 767.108477 433.706729 736.89851 451.162604 718.288414 483.422393 718.288414 518.334145 718.288414 553.245895 736.89851 585.505684 767.108477 602.961559 797.318425 620.417436 834.538616 620.417436 864.748584 602.961559 894.958532 585.505684 913.568627 553.245895 913.568627 518.334145L913.568627 518.334145ZM581.566143 215.288946C581.566143 215.288946 593.269057 203.098427 620.669932 203.098427 650.6546 203.098427 674.950626 227.414165 674.950626 257.423171 674.950626 290.452615 648.917554 305.250663 636.758739 309.031723 568.451875 353.599725 523.116685 430.436655 523.116685 518.116824 523.116685 605.970743 568.603889 682.938067 637.149606 727.440872 650.915177 731.852057 674.950626 743.064634 674.950626 778.940765 674.950626 808.949772 650.6546 833.265507 620.669932 833.265507 593.269057 833.265507 581.566143 821.07499 581.566143 821.07499 481.233659 757.536806 414.403283 645.801687 414.403283 518.181916 414.403283 390.562145 481.233659 278.805502 581.566143 215.288946L581.566143 215.288946ZM348.376225 14.135304C348.376225 14.135304 365.941399 7.529394 392.690949 7.529394 428.668185 7.529394 457.82781 36.73442 457.82781 72.719107 457.82781 98.186537 406.282822 128.195544 388.54391 137.474179 297.265513 229.695819 240.704994 356.381112 240.704994 496.452082 240.704994 650.321426 309.055287 787.849957 416.661363 881.418878 440.740242 890.980031 457.82781 914.426591 457.82781 941.914889 457.82781 977.899576 428.668185 1007.104602 392.690949 1007.104602 363.314276 1007.104602 345.336511 998.13011 345.336511 998.13011 202.12236 882.635664 110.431373 705.732666 110.431373 507.316947 110.431373 307.532423 203.446734 129.564556 348.376225 14.135304L348.376225 14.135304Z"
|
||||||
|
fill="#000000"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<audio
|
||||||
|
ref={audioRef}
|
||||||
|
src={`/api/${msg.path}`}
|
||||||
|
style={{ display: `${open ? 'block' : 'none'}` }}
|
||||||
|
controls
|
||||||
|
></audio>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
} catch (_e) {
|
} catch (_e) {
|
||||||
return (
|
return (
|
||||||
|
50
src/pages/ChatLogs/components/ChatVoiptext.tsx
Normal file
50
src/pages/ChatLogs/components/ChatVoiptext.tsx
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import { durationFormat } from '@/services/utils';
|
||||||
|
import { IChatItem } from '../ChatLogsType';
|
||||||
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
|
export const ChatVoiptext: React.FC<IChatItem> = (props) => {
|
||||||
|
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={{ wordBreak: 'break-all', paddingRight: 8 }}>
|
||||||
|
音视频通话 {durationFormat(msg.callduration)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} catch (_e) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div style={{ wordBreak: 'break-all', paddingRight: 8 }}>{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>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
54
src/pages/ChatLogs/components/ChatWeapp.tsx
Normal file
54
src/pages/ChatLogs/components/ChatWeapp.tsx
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
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);
|
||||||
|
|
||||||
|
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>
|
||||||
|
);
|
||||||
|
} catch (_e) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div style={{ wordBreak: 'break-all', paddingRight: 8 }}>{props.chat?.content}</div>
|
||||||
|
<FileTextFilled style={{ fontSize: 40, color: '#FA9D3B', flexShrink: 0 }} />
|
||||||
|
</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>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
@@ -12,7 +12,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.chatAvatar {
|
.chatAvatar {
|
||||||
|
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
width: 34px;
|
width: 34px;
|
||||||
height: 34px;
|
height: 34px;
|
||||||
@@ -109,3 +108,11 @@
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.imgPreview {
|
||||||
|
& > div {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -124,9 +124,9 @@ const ChatLogs: React.FC = () => {
|
|||||||
if (res.err_code == 0) {
|
if (res.err_code == 0) {
|
||||||
if (Array.isArray(res.data)) {
|
if (Array.isArray(res.data)) {
|
||||||
if (param.curr_page == 1) {
|
if (param.curr_page == 1) {
|
||||||
setChatLogs([...res.data, { curr_page: param.curr_page }]);
|
setChatLogs([...res.data.reverse(), { curr_page: param.curr_page }]);
|
||||||
} else {
|
} else {
|
||||||
setChatLogs([...res.data, { curr_page: param.curr_page }, ...chatLogs]);
|
setChatLogs([...res.data.reverse(), { curr_page: param.curr_page }, ...chatLogs]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -270,28 +270,28 @@ const ChatLogs: React.FC = () => {
|
|||||||
></div>
|
></div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (timeDiffRef.current == '') {
|
// if (timeDiffRef.current == '') {
|
||||||
timeDiffRef.current = item.msg_time;
|
// timeDiffRef.current = item.msg_time;
|
||||||
timeShowRef.current = false;
|
// timeShowRef.current = false;
|
||||||
} else {
|
// } else {
|
||||||
if (
|
// if (
|
||||||
Date.parse(item.msg_time) - Date.parse(timeDiffRef.current) >
|
// new Date(item.msg_time).getTime() - new Date(timeDiffRef.current).getTime() >
|
||||||
5 * 60 * 1000
|
// 5 * 60 * 1000
|
||||||
) {
|
// ) {
|
||||||
timeDiffRef.current = item.msg_time;
|
// timeDiffRef.current = item.msg_time;
|
||||||
timeShowRef.current = true;
|
// timeShowRef.current = true;
|
||||||
} else {
|
// } else {
|
||||||
timeShowRef.current = false;
|
// timeShowRef.current = false;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (i == 0) {
|
// if (i == 0) {
|
||||||
timeShowRef.current = true;
|
// timeShowRef.current = true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={item.msg_id}>
|
<div key={item.msg_id}>
|
||||||
{timeShowRef.current ? <ChatTime msgtime={item.msg_time}></ChatTime> : null}
|
<ChatTime msgtime={item.msg_time}></ChatTime>
|
||||||
<ChatBar from={selectStaff} to={selectCustFollow} chat={item}></ChatBar>
|
<ChatBar from={selectStaff} to={selectCustFollow} chat={item}></ChatBar>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@@ -35,3 +35,14 @@ export const notificationError = (message: IError) => {
|
|||||||
console.log('window.NotificationCF未绑定antd的notification');
|
console.log('window.NotificationCF未绑定antd的notification');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const durationFormat = (v: number) => {
|
||||||
|
const len = Number(v) || 0;
|
||||||
|
if (len > 60) {
|
||||||
|
return `${Math.floor(len / 60)
|
||||||
|
.toString()
|
||||||
|
.padStart(2, '0')}:${(len % 60).toString().padStart(2, '0')}`;
|
||||||
|
} else {
|
||||||
|
return `00:${len.toString().padStart(2, '0')}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Reference in New Issue
Block a user