|
|
|
@ -3,7 +3,6 @@ import { useParams, useNavigate, useLocation } from 'react-router-dom';
|
|
|
|
|
import { App, ConfigProvider, Button, Form, Input, Flex, Checkbox, Popconfirm, Select, Space, Upload, Divider, Modal, Tabs, Radio } from 'antd'
|
|
|
|
|
import { UploadOutlined, LoadingOutlined, SaveOutlined, SendOutlined, CheckCircleOutlined } from '@ant-design/icons'
|
|
|
|
|
import '@dckj/react-better-modal/dist/index.css'
|
|
|
|
|
import DnDModal from '@/components/DnDModal'
|
|
|
|
|
import useStyleStore from '@/stores/StyleStore'
|
|
|
|
|
// import useConversationStore from '@/stores/ConversationStore'
|
|
|
|
|
import useAuthStore from '@/stores/AuthStore'
|
|
|
|
@ -11,9 +10,9 @@ import useAuthStore from '@/stores/AuthStore'
|
|
|
|
|
import LexicalEditor from '@/components/LexicalEditor'
|
|
|
|
|
|
|
|
|
|
import { v4 as uuid } from 'uuid'
|
|
|
|
|
import { cloneDeep, debounce, isEmpty, writeIndexDB } from '@/utils/commons'
|
|
|
|
|
import { cloneDeep, debounce, isEmpty, writeIndexDB, readIndexDB, deleteIndexDBbyKey } from '@/utils/commons'
|
|
|
|
|
import '@/views/Conversations/Online/Input/EmailEditor.css'
|
|
|
|
|
import { postSendEmail } from '@/actions/EmailActions'
|
|
|
|
|
import { parseHTMLString, postSendEmail } from '@/actions/EmailActions'
|
|
|
|
|
import { sentMsgTypeMapped } from '@/channel/bubbleMsgUtils'
|
|
|
|
|
import { EmailBuilder, useEmailDetail, useEmailSignature } from '@/hooks/useEmail'
|
|
|
|
|
import useSnippetStore from '@/stores/SnippetStore'
|
|
|
|
@ -74,7 +73,7 @@ const generateMailContent = (mailData) => `<br><br><p>${mailData.content}</p>`
|
|
|
|
|
/**
|
|
|
|
|
* ! 无状态管理
|
|
|
|
|
*/
|
|
|
|
|
const NewEmail = ({ ...props }) => {
|
|
|
|
|
const NewEmail = () => {
|
|
|
|
|
const pageParam = useParams();
|
|
|
|
|
const editorKey = pageParam.action==='new' ? `new-${Date.now().toString(32)}` : `${pageParam.action}-${pageParam.quoteid}`
|
|
|
|
|
|
|
|
|
@ -121,18 +120,49 @@ const NewEmail = ({ ...props }) => {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const [contentPrefix, setContentPrefix] = useState('')
|
|
|
|
|
const [localDraft, setLocalDraft] = useState();
|
|
|
|
|
|
|
|
|
|
const readMailboxLocalCache = async () => {
|
|
|
|
|
const readCache = await readIndexDB(editorKey, 'draft', 'mailbox')
|
|
|
|
|
if (readCache) {
|
|
|
|
|
const btn = (
|
|
|
|
|
<Space>
|
|
|
|
|
<Button type='link' size='small' onClick={() => notification.destroy()}>
|
|
|
|
|
关闭
|
|
|
|
|
</Button>
|
|
|
|
|
{/* <Button type="primary" size="small" onClick={() => notification.destroy()}>
|
|
|
|
|
Confirm
|
|
|
|
|
</Button> */}
|
|
|
|
|
</Space>
|
|
|
|
|
)
|
|
|
|
|
// notification.open({
|
|
|
|
|
// key: editorKey,
|
|
|
|
|
// placement: 'top',
|
|
|
|
|
// // message: '提示',
|
|
|
|
|
// description: '已从本地缓存中读取邮件内容',
|
|
|
|
|
// duration: 0,
|
|
|
|
|
// actions: btn,
|
|
|
|
|
// })
|
|
|
|
|
setLocalDraft(readCache);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
readMailboxLocalCache()
|
|
|
|
|
|
|
|
|
|
return () => {}
|
|
|
|
|
}, [])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// const [stickToCid, setStickToCid] = useState(pageParam.conversationid)
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
console.log('useeffect\n', orderDetail.order_no);
|
|
|
|
|
// const propsObj = { ...activeEdit, mai: activeEdit.mailData?.info?.MAI_MAT_SN }
|
|
|
|
|
|
|
|
|
|
setContentPrefix(orderDetail.order_no ? `<p>Dear Mr./Ms. ${orderDetail.contact?.[0]?.name || ''}</p><p>Reference Number: ${orderDetail.order_no}</p>` : '')
|
|
|
|
|
|
|
|
|
|
return () => {}
|
|
|
|
|
}, [orderDetail.order_no])
|
|
|
|
|
}, [orderDetail.order_no, editorKey])
|
|
|
|
|
|
|
|
|
|
const handleSwitchEmail = (labelValue) => {
|
|
|
|
|
const handleSwitchEmail = (labelValue) => {
|
|
|
|
|
const { value } = labelValue
|
|
|
|
|
setNewFromEmail(value)
|
|
|
|
|
const _findMat = emailListAddrMapped?.[value]
|
|
|
|
@ -162,11 +192,18 @@ const NewEmail = ({ ...props }) => {
|
|
|
|
|
setHtmlContent(htmlContent)
|
|
|
|
|
setTextContent(textContent)
|
|
|
|
|
form.setFieldValue('content', htmlContent)
|
|
|
|
|
const { bodyText: abstract } = parseHTMLString(htmlContent, true);
|
|
|
|
|
const body = {
|
|
|
|
|
from: newFromEmail,
|
|
|
|
|
attaList: fileList,
|
|
|
|
|
opi_sn: emailOPI,
|
|
|
|
|
mat_sn: emailMat,
|
|
|
|
|
coli_sn: emailOrder || '',
|
|
|
|
|
}
|
|
|
|
|
// form.setFieldValue('abstract', getAbstract(textContent))
|
|
|
|
|
debouncedSave({ htmlContent, ...form.getFieldsValue() })
|
|
|
|
|
debouncedSave({ ...form.getFieldsValue(), ...body, htmlContent, abstract, })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const [initialForm, setInitialForm] = useState({})
|
|
|
|
|
const [initialContent, setInitialContent] = useState('')
|
|
|
|
|
const [showQuoteContent, setShowQuoteContent] = useState(false)
|
|
|
|
|
const [mergeQuote, setMergeQuote] = useState(true)
|
|
|
|
@ -176,9 +213,29 @@ const NewEmail = ({ ...props }) => {
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
console.log('useEffect 2---- \nform.setFieldsValue ');
|
|
|
|
|
const docTitle = localDraft?.subject || mailData.info?.MAI_Subject || 'New Email-';
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
document.title = mailData.info?.MAI_Subject || 'New Email-'
|
|
|
|
|
document.title = docTitle
|
|
|
|
|
}, 1500);
|
|
|
|
|
|
|
|
|
|
if (!isEmpty(localDraft)) {
|
|
|
|
|
const {htmlContent, ...draftFormsValues} = localDraft;
|
|
|
|
|
|
|
|
|
|
const _findMatOld = emailListMatMapped?.[draftFormsValues.mat_sn]
|
|
|
|
|
const _from = draftFormsValues?.from || _findMatOld?.email || ''
|
|
|
|
|
|
|
|
|
|
form.setFieldsValue(draftFormsValues);
|
|
|
|
|
setNewFromEmail(_from);
|
|
|
|
|
setEmailOPI(draftFormsValues.opi_sn)
|
|
|
|
|
setEmailMat(draftFormsValues.mat_sn)
|
|
|
|
|
setEmailOrder(draftFormsValues.coli_sn)
|
|
|
|
|
requestAnimationFrame(() => {
|
|
|
|
|
setInitialContent(htmlContent);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return () => {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 没有引用邮件
|
|
|
|
|
if (isEmpty(pageParam.quoteid)) {
|
|
|
|
|
|
|
|
|
@ -241,7 +298,6 @@ const NewEmail = ({ ...props }) => {
|
|
|
|
|
subject: `Re: ${info.MAI_Subject || ''}`,
|
|
|
|
|
}
|
|
|
|
|
form.setFieldsValue(_formValues)
|
|
|
|
|
setInitialForm(_formValues)
|
|
|
|
|
} else if (pageParam.action === 'replyall') {
|
|
|
|
|
const _formValues = {
|
|
|
|
|
to: info?.replyToAll || newFromEmail,
|
|
|
|
@ -250,10 +306,8 @@ const NewEmail = ({ ...props }) => {
|
|
|
|
|
subject: `Re: ${info.MAI_Subject || ''}`,
|
|
|
|
|
}
|
|
|
|
|
form.setFieldsValue(_formValues)
|
|
|
|
|
setInitialForm(_formValues)
|
|
|
|
|
} else if (pageParam.action === 'forward') {
|
|
|
|
|
form.setFieldsValue(forwardValues)
|
|
|
|
|
setInitialForm(forwardValues)
|
|
|
|
|
} else if (pageParam.action === 'edit') {
|
|
|
|
|
const thisFormValues = {
|
|
|
|
|
to: info?.MAI_To || '',
|
|
|
|
@ -261,20 +315,19 @@ const NewEmail = ({ ...props }) => {
|
|
|
|
|
subject: info?.MAI_Subject || '',
|
|
|
|
|
}
|
|
|
|
|
form.setFieldsValue(thisFormValues)
|
|
|
|
|
setInitialForm(thisFormValues)
|
|
|
|
|
const thisBody = generateMailContent(mailData)
|
|
|
|
|
// console.log('thisBody', thisBody);
|
|
|
|
|
|
|
|
|
|
setInitialContent(thisBody)
|
|
|
|
|
} else if (pageParam.action === 'new') {
|
|
|
|
|
const newEmail = { to: newToEmail, subject: pageParam.draft?.subject || '' }
|
|
|
|
|
// todo: 附件
|
|
|
|
|
const newEmail = { to: newToEmail, subject: '' }
|
|
|
|
|
form.setFieldsValue(newEmail)
|
|
|
|
|
setInitialForm(newEmail)
|
|
|
|
|
setInitialContent((pageParam.draft?.content || contentPrefix || '') + signatureBody)
|
|
|
|
|
setInitialContent((contentPrefix || '') + signatureBody)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return () => {}
|
|
|
|
|
}, [ mailData.info, signature, newToEmail])
|
|
|
|
|
}, [ mailData.info, signature, newToEmail, contentPrefix, localDraft])
|
|
|
|
|
|
|
|
|
|
const [openPlainTextConfirm, setOpenPlainTextConfirm] = useState(false)
|
|
|
|
|
const handlePlainTextOpenChange = ({ target }) => {
|
|
|
|
@ -463,13 +516,25 @@ const NewEmail = ({ ...props }) => {
|
|
|
|
|
bubbleMsg.email.mai_sn = mailSavedId
|
|
|
|
|
// console.log('invokeEmailMessage', bubbleMsg);
|
|
|
|
|
|
|
|
|
|
invokeEmailMessage(bubbleMsg)
|
|
|
|
|
// invokeEmailMessage(bubbleMsg)
|
|
|
|
|
|
|
|
|
|
// setSendLoading(false);
|
|
|
|
|
|
|
|
|
|
notification.success({
|
|
|
|
|
key: editorKey,
|
|
|
|
|
message: '成功',
|
|
|
|
|
// description: error.message,
|
|
|
|
|
placement: 'top',
|
|
|
|
|
duration: 2,
|
|
|
|
|
onClose: () => {
|
|
|
|
|
deleteIndexDBbyKey(editorKey, 'draft', 'mailbox');
|
|
|
|
|
window.close();
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
// setOpen(false)
|
|
|
|
|
} catch (error) {
|
|
|
|
|
notification.error({
|
|
|
|
|
key: editorKey,
|
|
|
|
|
message: '邮件保存失败',
|
|
|
|
|
description: error.message,
|
|
|
|
|
placement: 'top',
|
|
|
|
@ -489,7 +554,7 @@ const NewEmail = ({ ...props }) => {
|
|
|
|
|
debounce((data) => {
|
|
|
|
|
idleCallbackId.current = window.requestIdleCallback(() => {
|
|
|
|
|
console.log('Saving data (idle, debounced):', data)
|
|
|
|
|
writeIndexDB([{ ...data, key: editorKey }], 'draft', 'EmailEditor')
|
|
|
|
|
writeIndexDB([{ ...data, key: editorKey }], 'draft', 'mailbox')
|
|
|
|
|
})
|
|
|
|
|
}, 1500), // 1.5s
|
|
|
|
|
[],
|
|
|
|
@ -604,7 +669,7 @@ const NewEmail = ({ ...props }) => {
|
|
|
|
|
</Form.Item>
|
|
|
|
|
</Form>
|
|
|
|
|
<LexicalEditor {...{ isRichText }} onChange={handleEditorChange} defaultValue={initialContent} />
|
|
|
|
|
{pageParam.quoteid && !showQuoteContent && (
|
|
|
|
|
{pageParam.quoteid && pageParam.action!=='edit' && !showQuoteContent && (
|
|
|
|
|
<div className='flex justify-start items-center ml-2'>
|
|
|
|
|
<Button className='flex gap-2 ' type='link' onClick={() => setShowQuoteContent(!showQuoteContent)}>
|
|
|
|
|
显示引用内容 ↓ {/*(不可更改)*/}
|
|
|
|
|