From e113c33fc60b8843bc8ff437bff97bf3ccad2502 Mon Sep 17 00:00:00 2001 From: Lei OT Date: Tue, 10 Jun 2025 15:01:06 +0800 Subject: [PATCH] =?UTF-8?q?=E2=8F=B3=E6=96=B0=E7=AA=97=E5=8F=A3:=20?= =?UTF-8?q?=E9=82=AE=E4=BB=B6=E7=BC=96=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/actions/EmailActions.js | 2 +- src/stores/EmailSlice.js | 4 +- src/utils/commons.js | 2 +- src/views/NewEmail.jsx | 109 ++++++++++++++++++++++++++++-------- 4 files changed, 91 insertions(+), 26 deletions(-) diff --git a/src/actions/EmailActions.js b/src/actions/EmailActions.js index 34c4673..a133a94 100644 --- a/src/actions/EmailActions.js +++ b/src/actions/EmailActions.js @@ -3,7 +3,7 @@ import { API_HOST, DATE_FORMAT, DATEEND_FORMAT, DATETIME_FORMAT, EMAIL_HOST } fr import { buildTree, groupBy, isEmpty, objectMapper, omitEmpty, readIndexDB, uniqWith, writeIndexDB } from '@/utils/commons'; import dayjs from 'dayjs'; -const parseHTMLString = (html, needText = false) => { +export const parseHTMLString = (html, needText = false) => { const parser = new DOMParser() const doc = parser.parseFromString(html, 'text/html') let bodyContent = doc.body.innerHTML diff --git a/src/stores/EmailSlice.js b/src/stores/EmailSlice.js index 71bfe87..170b1e7 100644 --- a/src/stores/EmailSlice.js +++ b/src/stores/EmailSlice.js @@ -108,7 +108,7 @@ const emailSlice = (set, get) => ({ if (!isEmpty(readCache)) { setMailboxNestedDirsActive(readCache?.tree || []) isNeedRefresh = Date.now() - readCache.timestamp > 4 * 60 * 60 * 1000 - isNeedRefresh = true; // test: 0 + // isNeedRefresh = true; // test: 0 } if (isEmpty(readCache) || isNeedRefresh) { // > {4} 更新 @@ -120,7 +120,7 @@ const emailSlice = (set, get) => ({ async initMailbox({ opi_sn, dei_sn, userId, userIdStr }) { const { setCurrentMailboxOPI, setCurrentMailboxDEI, getOPIEmailDir } = get() - createIndexedDBStore(['dirs', 'maillist', 'mailinfo'], 'mailbox') + createIndexedDBStore(['dirs', 'maillist', 'mailinfo', 'draft'], 'mailbox') setCurrentMailboxOPI(opi_sn) setCurrentMailboxDEI(dei_sn) getOPIEmailDir(userId, userIdStr) diff --git a/src/utils/commons.js b/src/utils/commons.js index 463d8cd..80ceed4 100644 --- a/src/utils/commons.js +++ b/src/utils/commons.js @@ -862,7 +862,7 @@ export const readIndexDB = (key=null, table, database) => { getRequest.onsuccess = (event) => { const result = event.target.result if (result) { - console.log(`Found record with key ${key}:`, result) + console.log(`💾Found record with key ${key}:`, result) resolve(result) } else { console.log(`No record found with key ${key}.`) diff --git a/src/views/NewEmail.jsx b/src/views/NewEmail.jsx index 5658204..6097a1f 100644 --- a/src/views/NewEmail.jsx +++ b/src/views/NewEmail.jsx @@ -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) => `

${mailData.content}

` /** * ! 无状态管理 */ -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 = ( + + + {/* */} + + ) + // 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 ? `

Dear Mr./Ms. ${orderDetail.contact?.[0]?.name || ''}

Reference Number: ${orderDetail.order_no}

` : '') 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 }) => { - {pageParam.quoteid && !showQuoteContent && ( + {pageParam.quoteid && pageParam.action!=='edit' && !showQuoteContent && (