开发: 聊天页面修改
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">
|
<>
|
||||||
|
<div
|
||||||
|
className={styles.video}
|
||||||
|
onClick={() => {
|
||||||
|
setOpen(true);
|
||||||
|
videoRef.current.play().catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
<PlayCircleOutlined style={{ color: '#fff', fontSize: 40 }} />
|
<PlayCircleOutlined style={{ color: '#fff', fontSize: 40 }} />
|
||||||
<span className={styles.videoTime}>{playLen(msg.play_length)}</span>
|
<span className={styles.videoTime}>{playLen(msg.play_length)}</span>
|
||||||
</a>
|
</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,14 +1,39 @@
|
|||||||
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' }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
color: '#000',
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginBottom: 4,
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
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' }}>
|
<span style={{ lineHeight: 1, marginRight: 4, minWidth: 100, textAlign: 'right' }}>
|
||||||
{msg.play_length}"
|
{msg.play_length}"
|
||||||
</span>
|
</span>
|
||||||
@@ -18,7 +43,14 @@ export const ChatVoice: React.FC<IChatItem> = (props) => {
|
|||||||
fill="#000000"
|
fill="#000000"
|
||||||
></path>
|
></path>
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</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