|
|
|
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'
|
|
|
|
import EmailEditorPopup from './EmailEditorPopup'
|
|
|
|
import useStyleStore from '@/stores/StyleStore'
|
|
|
|
import useAuthStore from '@/stores/AuthStore'
|
|
|
|
// import { isEmpty, } from '@/utils/commons';
|
|
|
|
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()
|
|
|
|
|
|
|
|
const [mobile] = useStyleStore((state) => [state.mobile])
|
|
|
|
|
|
|
|
const { userId, username, emailList, email } = useAuthStore((state) => state.loginUser)
|
|
|
|
// const websocketOpened = useConversationStore((state) => state.websocketOpened);
|
|
|
|
const currentConversation = useConversationStore((state) => state.currentConversation)
|
|
|
|
// const talkabled = !isEmpty(currentConversation.sn) && websocketOpened;
|
|
|
|
const { orderDetail, customerDetail } = useOrderStore()
|
|
|
|
|
|
|
|
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 })
|
|
|
|
const [fromUser, setFromUser] = useState()
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
const order_opi = Number(orderDetail?.opi_sn || userId)
|
|
|
|
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])
|
|
|
|
|
|
|
|
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',
|
|
|
|
// to: currentConversation.whatsapp_phone_number,
|
|
|
|
date: new Date(),
|
|
|
|
status: 'waiting', // accepted
|
|
|
|
...msgObj,
|
|
|
|
// id: `${currentConversation.sn}.${msgObj.id}`,
|
|
|
|
// id: `${stickToCid}.${msgObj.id}`,
|
|
|
|
conversationid: currentConversation.sn,
|
|
|
|
msg_source: 'email',
|
|
|
|
};
|
|
|
|
// 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,
|
|
|
|
},
|
|
|
|
coli_id: orderDetail?.order_no || '',
|
|
|
|
}
|
|
|
|
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 (
|
|
|
|
<ConfigProvider theme={{ token: { colorPrimary: '#6366f1' } }}>
|
|
|
|
<Form
|
|
|
|
form={form}
|
|
|
|
preserve={false}
|
|
|
|
name='email_quick_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 tabIndex={1}
|
|
|
|
className='rounded-b-none border-b-0 font-bold text-base text-indigo-600'
|
|
|
|
placeholder='*主题'
|
|
|
|
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 tabIndex={2}
|
|
|
|
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 className={mobile ? 'w-24' : ''}
|
|
|
|
disabled={!talkabled} popupMatchSelectWidth={false}
|
|
|
|
// size={'small'}
|
|
|
|
options={emailListOption}
|
|
|
|
labelInValue
|
|
|
|
value={pickEmail}
|
|
|
|
onChange={(val) => {
|
|
|
|
setPickEmail(val)
|
|
|
|
setFromUser(emailListAddrMapped?.[val.value]?.opi_sn)
|
|
|
|
}}
|
|
|
|
// variant={'borderless'}
|
|
|
|
/>
|
|
|
|
<Button icon={<SendOutlined />} type='primary' htmlType={'submit'} disabled={!talkabled} loading={sendLoading} tabIndex={3}>
|
|
|
|
发送
|
|
|
|
</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}
|
|
|
|
oid={orderDetail?.order_no}
|
|
|
|
conversationid={currentConversation.sn}
|
|
|
|
toEmail={toEmail}
|
|
|
|
draft={quickData}
|
|
|
|
action='new'
|
|
|
|
key={'email-new-editor-popup'}
|
|
|
|
/>
|
|
|
|
</ConfigProvider>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
export default EmailComposer
|