You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Global-sales/src/views/Conversations/Online/Input/EmailComposer.jsx

269 lines
9.9 KiB
React

import { useState, useEffect, useRef } from 'react'
import { App, Button, ConfigProvider, Dropdown, Flex, Select, Input, Tooltip, Form } from 'antd'
import { DownOutlined, DollarOutlined, ExpandAltOutlined, ExpandOutlined, SendOutlined, } from '@ant-design/icons'
11 months ago
import EmailEditorPopup from './EmailEditorPopup'
import useStyleStore from '@/stores/StyleStore'
import useAuthStore from '@/stores/AuthStore'
// import { isEmpty, } from '@/utils/commons';
11 months ago
import useConversationStore from '@/stores/ConversationStore'
import { useOrderStore } from '@/stores/OrderStore'
import { EditIcon } from '@/components/Icons'
import { cloneDeep, isEmpty } from '@/utils/commons'
import { v4 as uuid } from 'uuid'
import { postSendEmail } from '@/actions/EmailActions'
import { sentMsgTypeMapped, } from '@/channel/bubbleMsgUtils';
import ComposerTools from './ComposerTools'
const EmailComposer = ({ ...props }) => {
const { notification } = App.useApp()
const [form] = Form.useForm()
11 months ago
const [mobile] = useStyleStore((state) => [state.mobile])
const { userId, username, emailList, email } = useAuthStore((state) => state.loginUser)
// const websocketOpened = useConversationStore((state) => state.websocketOpened);
11 months ago
const currentConversation = useConversationStore((state) => state.currentConversation)
// const talkabled = !isEmpty(currentConversation.sn) && websocketOpened;
const { orderDetail, customerDetail } = useOrderStore()
11 months ago
const emailListOption = emailList?.map((ele) => ({ ...ele, label: ele.email, key: ele.email, value: ele.email })) || []
const emailListAddrMapped = emailListOption?.reduce((r, v) => ({ ...r, [v.email]: v }), {});
const [pickEmail, setPickEmail] = useState({ key: email, email })
11 months ago
const [fromUser, setFromUser] = useState()
useEffect(() => {
const order_opi = Number(orderDetail?.opi_sn || userId)
11 months ago
setFromUser(order_opi)
const find =
emailListOption?.find((ele) => ele.opi_sn === order_opi && ele.default === true) ||
emailListOption?.find((ele) => ele.opi_sn === order_opi && ele.backup === true) ||
emailListOption?.find((ele) => ele.opi_sn === order_opi) ||
emailListOption?.find((ele) => ele.default === true) ||
emailListOption?.find((ele) => ele.backup === true) ||
emailListOption[0]
setPickEmail(find)
return () => {}
}, [orderDetail])
11 months ago
const [open, setOpen] = useState(false)
const [fromEmail, setFromEmail] = useState('')
const [toEmail, setToEmail] = useState('')
const lastFocusedFieldRef = useRef(null);
const textInputRef = useRef(null)
const websocketOpened = useConversationStore((state) => state.websocketOpened)
const talkabled = !isEmpty(currentConversation.sn) && websocketOpened
const [sendLoading, setSendLoading] = useState(false)
const [quickData, setQuickData] = useState({ suject: '', content: ''});
const handleFocus = (field) => {
lastFocusedFieldRef.current = field;
}
const addEmoji = (emoji) => {
const _field = lastFocusedFieldRef.current || 'mailcontent';
// if (focusedField) {
const fieldValue = form.getFieldValue(_field) || '';
const updatedValue = `${fieldValue}${emoji}`;
// form.setFieldsValue({ [_field]: updatedValue });
form.setFieldValue(_field, updatedValue)
form.focusField(_field)
// }
}
const openEditor = (email_addr) => {
setOpen(true)
setFromEmail(email_addr)
setToEmail(currentConversation?.channels?.email || customerDetail?.email || '')
setQuickData({
subject: form.getFieldValue('subject'),
content: form.getFieldValue('mailcontent'),
})
}
/**
* 保存成功, 推一个气泡
* 再从异步通知更新消息发送状态
*/
const sentOrReceivedNewMessage = useConversationStore((state) => state.sentOrReceivedNewMessage);
const invokeEmailMessage = (msgObj) => {
const msgObjMerge = {
sender: 'me',
senderName: 'me',
msg_source: 'email',
// to: currentConversation.whatsapp_phone_number,
date: new Date(),
status: 'waiting', // accepted
...msgObj,
// id: `${currentConversation.sn}.${msgObj.id}`,
// id: `${stickToCid}.${msgObj.id}`,
conversationid: currentConversation.sn,
};
// olog('invoke upload', msgObjMerge)
const contentToRender = sentMsgTypeMapped[msgObjMerge.type].contentToRender(msgObjMerge);
// console.log(contentToRender, 'contentToRender sendMessage------------------');
sentOrReceivedNewMessage(contentToRender.conversationid, contentToRender);
};
// const [quickValidateHelp, setQuickValidateHelp] = useState('')
const handleSendEmail = async (values) => {
// console.log('invoke email message');
const emailAccount = { opi_sn: fromUser, email: pickEmail.key, mat_sn: '' };
emailAccount.opi_sn = fromUser || emailListAddrMapped?.[emailAccount.email]?.opi_sn || '';
emailAccount.mat_sn = emailListAddrMapped?.[emailAccount.email]?.mat_sn || '';
const stickToCid = currentConversation.sn
const body = {}
body.subject = values.subject
body.mailcontent = values.mailcontent
body.from = emailAccount.email
body.to = currentConversation.channels?.email || customerDetail?.email || ''
// body.attaList = fileList;
body.opi_sn = emailAccount.opi_sn
body.mat_sn = emailAccount.mat_sn
body.coli_sn = currentConversation?.coli_sn || ''
// console.log('body', body, '\n')
body.cc = ''
body.bcc = ''
const msgObj = {
type: 'email',
id: uuid(),
from: body.from,
to: body.to,
cc: '',
bcc: '',
subject: values.subject,
content: body.mailcontent,
email: {
subject: values.subject,
content: body.mailcontent,
},
}
setSendLoading(true)
body.externalID = stickToCid
body.actionID = `${stickToCid}.${msgObj.id}`
try {
const bubbleMsg = cloneDeep(msgObj)
bubbleMsg.id = `${stickToCid}.${msgObj.id}`
bubbleMsg.content = undefined
// console.log('email message', body, '\n', bubbleMsg)
const result = await postSendEmail(body)
const mailSavedId = result.id || ''
bubbleMsg.email.mai_sn = mailSavedId
invokeEmailMessage(bubbleMsg)
form.resetFields();
} catch (error) {
notification.error({
message: '邮件保存失败',
description: error.message,
placement: 'top',
duration: 3,
})
} finally {
setSendLoading(false)
}
}
return (
11 months ago
<ConfigProvider theme={{ token: { colorPrimary: '#6366f1' } }}>
<Form
form={form}
preserve={false}
name='email_max_form'
layout={'inline'}
// initialValues={{}}
onFinish={handleSendEmail}
onFinishFailed={console.log}
className=''
>
<Form.Item name='from' className='hidden'></Form.Item>
<Form.Item name='to' className='hidden'></Form.Item>
<Form.Item name='cc' className='hidden'></Form.Item>
<Form.Item name='bcc' className='hidden'></Form.Item>
<Form.Item name='subject' className='w-full' rules={[{ required: true, message: '' }]}>
<Input
className='rounded-b-none border-b-0 font-bold text-base text-indigo-600'
placeholder='*主题'
10 months ago
disabled={!talkabled} allowClear
onFocus={() => handleFocus('subject')}
suffix={
<Tooltip title={'全文编辑'}>
<Button
type='text'
size='small'
onClick={() => openEditor(pickEmail.key)}
icon={<ExpandOutlined className='text-indigo-600' />}
/>
</Tooltip>
}
/>
</Form.Item>
<Form.Item name='mailcontent' className='w-full' rules={[{ required: true, message: '' }]}>
<Input.TextArea
allowClear
ref={textInputRef}
onFocus={() => handleFocus('mailcontent')}
size='large'
maxLength={2000}
showCount={true}
placeholder={!talkabled ? '请先选择会话' : '*纯文本邮件'}
rows={2}
disabled={!talkabled}
className='rounded-none emoji'
autoSize={{ minRows: 2, maxRows: 6 }}
/>
</Form.Item>
<Flex gap={8} className='w-full bg-gray-200 p-1 rounded-b-0' align={'center'} justify={'space-between'}>
<ComposerTools key={'et'} channel={'email'} inputEmoji={addEmoji} />
{/* <span>切换邮箱:</span>*/}
<Flex gap={4} align={'center'}>
<div className='text-red-500'>
{/* <div>{textPlaceHolder}</div> */}
{/* {quickValidateHelp} */}
</div>
<Select
disabled={!talkabled}
// size={'small'}
options={emailListOption}
labelInValue
value={pickEmail}
onChange={(val) => {
setPickEmail(val)
setFromUser(val.opi_sn)
}}
// variant={'borderless'}
/>
<Button icon={<SendOutlined />} type='primary' htmlType={'submit'} disabled={!talkabled} loading={sendLoading} _onClick={() => handleSendEmail()}>
发送
</Button>
{/* <Button icon={<EditIcon />} type='primary' onClick={() => openEditor(pickEmail.key)}>
新邮件
</Button> */}
</Flex>
</Flex>
</Form>
<EmailEditorPopup
{...{ open, setOpen }}
fromEmail={fromEmail}
fromUser={fromUser}
fromOrder={currentConversation.coli_sn}
conversationid={currentConversation.sn}
toEmail={toEmail}
quickData={quickData}
action='new'
key={'email-new-editor-popup'}
/>
11 months ago
</ConfigProvider>
)
}
export default EmailComposer