diff --git a/src/actions/EmailActions.js b/src/actions/EmailActions.js index c32e40e..8908968 100644 --- a/src/actions/EmailActions.js +++ b/src/actions/EmailActions.js @@ -167,7 +167,7 @@ const todoTypes = { */ export const getEmailDirAction = async (params = { opi_sn: '' }) => { const defaultParams = { opi_sn: 0, year: dayjs().year(), by_start_date: -1, by_success: -1, important: -1, if_want_book: -1, if_thinking: -1 } - const { errcode, result } = await fetchJSON(`${API_HOST}/v3/email_dir`, { ...defaultParams, ...params }) + const { errcode, result } = await fetchJSON(`${API_HOST}/email_dir`, { ...defaultParams, ...params }) const mailboxSort = result //.sort(sortBy('MDR_Order')); let tree = buildTree(mailboxSort, { key: 'VKey', parent: 'VParent', name: 'VName', iconIndex: 'ImageIndex', rootKeys: [1], ignoreKeys: [-227001, -227002] }) tree = tree.filter((ele) => ele.key !== 1) @@ -309,7 +309,7 @@ export const queryEmailListAction = async ({ opi_sn = '', pagesize = 10, last_id } _params.mai_senddate1 = dayjs(_params.mai_senddate1).format(DATE_FORMAT) const cacheKey = isEmpty(_params.coli_sn) ? `dir-${node.vkey}` : `order-${node.vkey}`; - const { errcode, result } = await fetchJSON(`${API_HOST}/v3/mail_list`, _params) + const { errcode, result } = await fetchJSON(`${API_HOST}/mail_list`, _params) const ret = errcode === 0 ? result : [] if (!isEmpty(ret)) { const listids = [...new Set(ret.map(ele => ele.MAI_SN))]; @@ -337,7 +337,7 @@ export const updateEmailAction = async (params = { mai_sn_list: [], set: {} }) = * @param {number} [params.remind_index] - Index of the reminder. */ export const getEmailTemplateAction = async (params = { coli_sn: 0, lgc: 1, opi_sn: 0, remind_type: '', remind_index: 0 }) => { - const { errcode, result } = await fetchJSON(`${API_HOST}/v3/reminder_letter`, params) + const { errcode, result } = await fetchJSON(`${API_HOST}/reminder_letter`, params) const { html, bodyContent, bodyText } = parseHTMLString(result?.MailContent, true) ; return errcode === 0 ? {...result, bodyContent }: {} } @@ -348,24 +348,25 @@ export const getEmailTemplateAction = async (params = { coli_sn: 0, lgc: 1, opi_ * @param {boolean} [isDraft=false] - Whether the email is a draft. */ export const saveEmailDraftOrSendAction = async (body, isDraft = false) => { - const url = isDraft !== false ? `${API_HOST}/v3/email_draft_save` : `${EMAIL_HOST}/sendmail`; + const url = isDraft !== false ? `${API_HOST}/email_draft_save` : `${EMAIL_HOST}/sendmail`; const { attaList=[], atta, content, ...bodyData } = body; bodyData.ordertype = 227001; const formData = new FormData(); Object.keys(bodyData).forEach(function (key) { - formData.append(key, bodyData[key]); + formData.append(key, bodyData[key] || ''); }); - attaList.forEach(function (item) { + // 附件只传新增的 + attaList.filter(ele => !ele.fullPath).forEach(function (item) { formData.append('attachment', item); }); - const { result } = await postForm(url, formData); - return result; + const { errcode, result } = await postForm(url, formData); + return errcode === 0 ? (result || {}) : {} }; /** - * 删除邮件草稿 + * 删除邮件附件 */ -export const deleteEmailDraftAction = async (id) => { - const { errcode, result } = await postJSON(`${EMAIL_HOST}/email-draft/delete`, { id }) - return errcode === 0 ? {} : result +export const deleteEmailAttachmentAction = async (ati_sn_list) => { + const { errcode, result } = await postJSON(`${API_HOST}/mail_attachment_delete`, { ati_sn_list }) + return errcode === 0 ? result : {} }; diff --git a/src/config.js b/src/config.js index 0a8df09..1df0504 100644 --- a/src/config.js +++ b/src/config.js @@ -6,7 +6,7 @@ // export const WS_URL = 'wss://p9axztuwd7x8a7.mycht.cn/whatsapp_144'; // prod: Slave // debug: -export const API_HOST = 'http://202.103.68.144:8889/v2'; +export const API_HOST = 'http://202.103.68.144:8889/v3'; // export const WS_URL = 'ws://202.103.68.144:8888'; // export const EMAIL_HOST = 'http://202.103.68.231:888/service-mail'; // export const WAI_HOST = 'http://47.83.248.120/api/v1'; // 香港服务器 diff --git a/src/hooks/useEmail.js b/src/hooks/useEmail.js index e8045fc..8d4addb 100644 --- a/src/hooks/useEmail.js +++ b/src/hooks/useEmail.js @@ -1,6 +1,6 @@ import { useState, useEffect, useCallback } from 'react' import { isEmpty, objectMapper, olog, readIndexDB, } from '@/utils/commons' -import { getEmailDetailAction, postResendEmailAction, getSalesSignatureAction, getEmailOrderAction, queryEmailListAction, getEmailTemplateAction } from '@/actions/EmailActions' +import { getEmailDetailAction, postResendEmailAction, getSalesSignatureAction, getEmailOrderAction, queryEmailListAction, getEmailTemplateAction, saveEmailDraftOrSendAction } from '@/actions/EmailActions' import { App } from 'antd' import useConversationStore from '@/stores/ConversationStore'; import { msgStatusRenderMapped } from '@/channel/bubbleMsgUtils'; @@ -44,79 +44,96 @@ export const useEmailDetail = (mai_sn, data={}, oid=0) => { const {notification} = App.useApp() const [loading, setLoading] = useState(false) const [mailData, setMailData] = useState({ loading, info: { MAI_COLI_SN: 0 }, content: '', attachments: [], AttachList: [] }) + const [maiSN, setMaiSN] = useState(mai_sn); const [coliSN, setColiSN] = useState(oid); const [orderDetail, setOrderDetail] = useState({}); - const [updateMessageItem] = useConversationStore(state => [state.updateMessageItem]); + const [refreshTrigger, setRefreshTrigger] = useState(0); + const refresh = useCallback(() => { + setRefreshTrigger(prev => prev + 1); + }, []); - useEffect(() => { - const getEmailDetail = async () => { - if (isEmpty(Number(mai_sn))) { - return false - } - try { - setLoading(true) - const data = await getEmailDetailAction({ mai_sn }) - // console.log(data) - setMailData(data) - setColiSN(oid===false ? 0 : data.info.MAI_COLI_SN) - // if (!isEmpty(data.info.MAI_COLI_SN)) { - // const orderData = await getEmailOrderAction({ colisn: data.info.MAI_COLI_SN }) - // setOrderDetail(orderData) - // // console.log(orderData) - // } - setLoading(false) - } catch (err) { - setLoading(false) - notification.error({ - message: "请求失败", - description: err.message || '网络异常', - placement: "top", - duration: 3, - }); - } + // const [updateMessageItem] = useConversationStore(state => [state.updateMessageItem]); + + const getEmailDetail = useCallback(async () => { + if (isEmpty(Number(maiSN)) && isEmpty(Number(mai_sn))) { + return false } - if (isEmpty(data)) getEmailDetail() - else setMailData(data) - }, [mai_sn]) + if (!isEmpty(data)) { + setMailData(data) + return false + } + try { + setLoading(true) + const data = await getEmailDetailAction({ mai_sn: maiSN || mai_sn }) + // console.log(data) + setMailData(data) + setColiSN(oid === false ? 0 : data.info.MAI_COLI_SN) + setLoading(false) + } catch (err) { + setLoading(false) + notification.error({ + message: '请求失败', + description: err.message || '网络异常', + placement: 'top', + duration: 3, + }) + } + }, [mai_sn, maiSN, refreshTrigger]) - useEffect(() => { - console.log(coliSN, '====colisn======') - const getOrderDetail = async () => { - if (isEmpty(Number(coliSN))) { - return false - } - try { - setLoading(true) - const data = await getEmailOrderAction({ colisn: coliSN }) - setOrderDetail(data) - setLoading(false) - } catch (err) { - setLoading(false) - notification.error({ - message: "请求失败", - description: err.message || '网络异常', - placement: "top", - duration: 3, - }); - } + + const getOrderDetail = useCallback(async () => { + // console.log(coliSN, '====colisn======') + if (isEmpty(Number(coliSN))) { + return false + } + try { + setLoading(true) + const data = await getEmailOrderAction({ colisn: coliSN }) + setOrderDetail(data) + setLoading(false) + } catch (err) { + setLoading(false) + notification.error({ + message: '请求失败', + description: err.message || '网络异常', + placement: 'top', + duration: 3, + }) } + }, [coliSN]) + useEffect(() => { + getEmailDetail(); + }, [getEmailDetail]) + + useEffect(() => { getOrderDetail() - }, [coliSN]) + }, [getOrderDetail]) const postEmailResend = async ({ mai_sn, conversationid: externalid, actionId: actionid, ...body }) => { - if (isEmpty(mai_sn)) { + if (isEmpty(Number(mai_sn))) { return false } await postResendEmailAction({ mai_sn, externalid, actionid, token: 0 }) // 重发没有状态返回值, 此处前端处理为'待发送', todo: 刷新页面后消息仍为上一个状态'失败' - updateMessageItem({ conversationid: externalid, actionid, id: actionid, status: msgStatusRenderMapped['accepted'] }) + // updateMessageItem({ conversationid: externalid, actionid, id: actionid, status: msgStatusRenderMapped['accepted'] }) } - return { loading, mailData, orderDetail, postEmailResend } + const postEmailSaveOrSend = async (body, isDraft) => { + try { + const { id: savedID } = await saveEmailDraftOrSendAction(body, isDraft) + setMaiSN(savedID) + refresh() + return savedID + } catch (error) { + console.error(error); + } + }; + + return { loading, mailData, orderDetail, postEmailResend, postEmailSaveOrSend } } export const EmailBuilder = ({subject, content}) => { diff --git a/src/views/Conversations/Online/Components/EmailDetailInline.jsx b/src/views/Conversations/Online/Components/EmailDetailInline.jsx index 9bebb6b..d16bdf4 100644 --- a/src/views/Conversations/Online/Components/EmailDetailInline.jsx +++ b/src/views/Conversations/Online/Components/EmailDetailInline.jsx @@ -68,9 +68,7 @@ const EmailDetailInline = ({ mailID, emailMsg = {}, disabled = false, variant, s }, [mailID]) const onOpenEditor = (msgOrigin, action='reply') => { - window.open(`/email/${action}/${mailID || 0}`, `${action}-${mailID || 0}`,POPUP_FEATURES) - console.log('first000', emailMsg) - console.log('first', msgOrigin) + openPopup(`/email/${action}/${mailID || 0}`, `${action}-${mailID || 0}`) if (typeof props.onOpenEditor === 'function') { props.onOpenEditor(msgOrigin, action); } else { @@ -256,7 +254,7 @@ const EmailDetailInline = ({ mailID, emailMsg = {}, disabled = false, variant, s - openPopup(`${EMAIL_ATTA_HOST}${atta.ATI_ServerFile}`, atta.ATI_SN, POPUP_FEATURES)} size='small' className='text-blue-500 cursor-pointer'> + openPopup(`${EMAIL_ATTA_HOST}${atta.ATI_ServerFile}`, atta.ATI_SN)} size='small' className='text-blue-500 cursor-pointer'> {atta.ATI_Name} diff --git a/src/views/NewEmail.jsx b/src/views/NewEmail.jsx index e1fe20f..8de9a68 100644 --- a/src/views/NewEmail.jsx +++ b/src/views/NewEmail.jsx @@ -10,16 +10,16 @@ import useAuthStore from '@/stores/AuthStore' import LexicalEditor from '@/components/LexicalEditor' import { v4 as uuid } from 'uuid' -import { cloneDeep, debounce, isEmpty, writeIndexDB, readIndexDB, deleteIndexDBbyKey, olog } from '@/utils/commons' +import { cloneDeep, debounce, isEmpty, writeIndexDB, readIndexDB, deleteIndexDBbyKey, olog, omitEmpty } from '@/utils/commons' import '@/views/Conversations/Online/Input/EmailEditor.css' -import { parseHTMLString, postSendEmail, saveEmailDraftOrSendAction } from '@/actions/EmailActions' +import { deleteEmailAttachmentAction, parseHTMLString, postSendEmail, saveEmailDraftOrSendAction } from '@/actions/EmailActions' import { sentMsgTypeMapped } from '@/channel/bubbleMsgUtils' -import { EmailBuilder, useEmailDetail, useEmailSignature, useEmailTemplate } from '@/hooks/useEmail' +import { EmailBuilder, openPopup, useEmailDetail, useEmailSignature, useEmailTemplate } from '@/hooks/useEmail' import useSnippetStore from '@/stores/SnippetStore' // import { useOrderStore } from '@/stores/OrderStore' import PaymentlinkBtn from '@/views/Conversations/Online/Input/PaymentlinkBtn' import { TextIcon } from '@/components/Icons'; -import { POPUP_FEATURES } from '@/config'; +import { EMAIL_ATTA_HOST, POPUP_FEATURES } from '@/config'; // 禁止上传的附件类型 // .application, .exe, .app @@ -92,23 +92,16 @@ const NewEmail = () => { // console.log('emailListMapped', emailListOption, emailListAddrMapped); const mai_sn = pageParam.quoteid // activeEdit.quoteid - const { loading: quoteLoading, mailData, orderDetail } = useEmailDetail(mai_sn, null, pageParam.oid) + const { loading: quoteLoading, mailData, orderDetail, postEmailSaveOrSend } = useEmailDetail(mai_sn, null, pageParam.oid) const { loading: loadingTamplate, templateContent } = useEmailTemplate(templateKey, {coli_sn: pageParam.oid, opi_sn: orderDetail.opi_sn || mailData.info?.MAI_OPI_SN || 0, lgc: 1}); const { signature } = useEmailSignature(orderDetail.opi_sn || mailData.info?.MAI_OPI_SN || 0) - const [newFromEmail, setNewFromEmail] = useState('') - const [newToEmail, setNewToEmail] = useState('') - const [emailOPI, setEmailOPI] = useState('') - const [emailOrder, setEmailOrder] = useState('') - const [emailOrderSN, setEmailOrderSN] = useState('') - const [emailMat, setEmailMat] = useState('') - - const stateReset = () => { - setEmailOrder('') - setEmailOPI('') - setNewFromEmail('') - setNewToEmail('') - } + // const [newFromEmail, setNewFromEmail] = useState('') + // const [newToEmail, setNewToEmail] = useState('') + // const [emailOPI, setEmailOPI] = useState('') + // const [emailOrder, setEmailOrder] = useState('') + // const [emailOrderSN, setEmailOrderSN] = useState('') + // const [emailMat, setEmailMat] = useState('') const [contentPrefix, setContentPrefix] = useState('') const [localDraft, setLocalDraft] = useState(); @@ -165,13 +158,16 @@ const NewEmail = () => { // - 从原邮件内容 // - 从订单 useEffect(() => { - console.log('useEffect 1---- \nform.setFieldsValue '); + // console.log('useEffect 1---- \nform.setFieldsValue '); if (isEmpty(mailData.content) && isEmpty(orderDetail.order_no)) { return () => {} } const docTitle = mailData.info?.MAI_Subject || 'New Email-'; document.title = docTitle + const { order_no } = orderDetail + setContentPrefix(order_no ? `

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

Reference Number: ${order_no}

` : '') + const { info } = mailData const { ...templateFormValues } = templateContent; @@ -183,13 +179,12 @@ const NewEmail = () => { const _findMatOldE = emailListMatMapped?.[info.MAI_MAT_SN] const quotedMailSender = _findMatOldE?.email || '' - const sender = quotedMailSender || orderSender const quotedMailSenderObj = sender; // { key: sender, label: sender, value: sender } const defaultMAT = emailListAddrMapped?.[sender]?.mat_sn || '' const _form2 = { - coli_sn: pageParam.oid || info?.coli_sn || '', + coli_sn: Number(pageParam.oid) || info?.MAI_COLI_SN || '', mat_sn: info?.MAI_MAT_SN || defaultMAT, opi_sn: info?.MAI_OPI_SN || orderDetail.opi_sn || '', } @@ -248,21 +243,24 @@ const NewEmail = () => { ..._form2 } readyToInitialContent = generateMailContent(mailData) + setFileList(mailData.attachments.map(ele => ({ uid: ele.ATI_SN, name: ele.ATI_Name, url: ele.ATI_ServerFile, fullPath: `${EMAIL_ATTA_HOST}${ele.ATI_ServerFile}` }))) break case 'new': _formValues = { ...templateFormValues, from: quotedMailSenderObj, - to: orderReceiver, - ..._form2 + to: orderReceiver || info?.MAI_To || '', + subject: `${info.MAI_Subject || ''}`, + ..._form2, } - readyToInitialContent = generateMailContent({ content: templateContent.bodycontent }) + readyToInitialContent = generateMailContent({ content: templateContent.bodycontent || '' }) + setFileList(mailData.attachments.map(ele => ({ uid: ele.ATI_SN, name: ele.ATI_Name, url: ele.ATI_ServerFile, fullPath: `${EMAIL_ATTA_HOST}${ele.ATI_ServerFile}` }))) break default: break } - olog('222', _formValues, pageParam.action) + // olog('222', _formValues, pageParam.action) form.setFieldsValue(_formValues) // todo: from setInitialContent(readyToInitialContent); @@ -306,27 +304,13 @@ const NewEmail = () => { return () => {} }, [loadingTamplate]) - - - useEffect(() => { - console.log('useeffect\n', orderDetail.order_no); - - setContentPrefix(orderDetail.order_no ? `

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

Reference Number: ${orderDetail.order_no}

` : '') - // form.setFieldsValue({ to: orderDetail.contact?.[0]?.email || '' }) - setNewToEmail(orderDetail.contact?.[0]?.email || '') - - return () => {} - }, [orderDetail.order_no, editorKey]) - - const handleSwitchEmail = (labelValue) => { - const { value } = labelValue - setNewFromEmail(value) + const handleSwitchEmail = (value) => { + // const { value } = labelValue + // setNewFromEmail(value) const _findMat = emailListAddrMapped?.[value] - setEmailMat(_findMat?.mat_sn) - setEmailOPI(_findMat?.opi_sn) + form.setFieldsValue({ mat_sn: _findMat?.mat_sn, opi_sn: _findMat?.opi_sn }) } - const [isRichText, setIsRichText] = useState(mobile === false) // const [isRichText, setIsRichText] = useState(false); // 默认纯文本 const [htmlContent, setHtmlContent] = useState('') @@ -348,125 +332,17 @@ const NewEmail = () => { 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({ ...form.getFieldsValue(), ...body, htmlContent, abstract, }) + const formValues = omitEmpty(form.getFieldsValue()); + if (!isEmpty(formValues)) { + debouncedSave({ ...form.getFieldsValue(), htmlContent, abstract, }) + } } const [initialContent, setInitialContent] = useState('') const [showQuoteContent, setShowQuoteContent] = useState(false) - // const [mergeQuote, setMergeQuote] = useState(true) const [quoteContent, setQuoteContent] = useState('') - // const setPreFillInProperty = () => { }; - - // useEffect(() => { - // console.log('useEffect 2---- \nform.setFieldsValue '); - // const docTitle = localDraft?.subject || mailData.info?.MAI_Subject || 'New Email-'; - // setTimeout(() => { - // document.title = docTitle - // }, 1500); - - // // 没有引用邮件 - // if (isEmpty(pageParam.quoteid)) { - - // // setEmailOrder(orderDetail.order_no) - // // setEmailOPI(orderDetail.opi_sn) - // // setNewFromEmail(activeEdit.fromEmail) - // // setNewToEmail(activeEdit.toEmail) - - // // const _findMat = emailListAddrMapped?.[activeEdit.fromEmail]?.mat_sn - // // setEmailMat(_findMat) - - // // if (open !== true) { - // // form.resetFields() - // // } - // } - // // 转发/回复时, 使用详情的账户信息 - // if (mailData.info?.MAI_MAT_SN) { - // const reEmailO = mailData.info?.MAI_COLI_SN - // const reEmailUser = mailData.info?.MAI_OPI_SN - // const reEmailUserMat = mailData.info?.MAI_MAT_SN - - // setEmailOrder((prev) => reEmailO || prev ) // activeEdit.fromOrder - // setEmailOPI((prev) => reEmailUser || prev) - // setEmailMat((prev) => reEmailUserMat || prev) - - // const _findMatOld = emailListMatMapped?.[reEmailUserMat] - // if (_findMatOld) { - // setNewFromEmail(_findMatOld.email) - // setEmailOPI(_findMatOld.opi_sn) - // setEmailMat(_findMatOld.mat_sn) - // } - // } - // setShowQuoteContent(false) - // // setMergeQuote(true) - // setQuoteContent('') - - - // if (isEmpty(pageParam.quoteid) && pageParam.action !== 'new') { - // return () => {} - // } - // const { info } = mailData - // // setShowCc(!isEmpty(mailData.info?.MAI_CS)); - - // const signatureBody = generateMailContent({ content: signature }) - - // // const preQuoteBody = generateQuoteContent(mailData) - - // // const _initialContent = isEmpty(mailData.info) ? signatureBody : signatureBody+preQuoteBody - - // if (!isEmpty(mailData.info) && pageParam.action !== 'edit') { - // setInitialContent(contentPrefix + signatureBody) - // } - - // const forwardValues = { from: newFromEmail, subject: `Fw: ${info.MAI_Subject || ''}` } - // if (pageParam.action === 'reply') { - // const _formValues = { - // to: info?.replyTo || newFromEmail, - // cc: info?.MAI_CS || '', - // // bcc: quote.bcc || '', - // subject: `Re: ${info.MAI_Subject || ''}`, - // } - // form.setFieldsValue(_formValues) - // } else if (pageParam.action === 'replyall') { - // const _formValues = { - // to: info?.replyToAll || newFromEmail, - // cc: info?.MAI_CS || '', - // // bcc: quote.bcc || '', - // subject: `Re: ${info.MAI_Subject || ''}`, - // } - // form.setFieldsValue(_formValues) - // } else if (pageParam.action === 'forward') { - // form.setFieldsValue(forwardValues) - // } else if (pageParam.action === 'edit') { - // const thisFormValues = { - // to: info?.MAI_To || '', - // cc: info?.MAI_CS || '', - // subject: info?.MAI_Subject || '', - // id: pageParam.quoteid, - // } - // form.setFieldsValue(thisFormValues) - // const thisBody = generateMailContent(mailData) - // // console.log('thisBody', thisBody); - - // setInitialContent(thisBody) - // } else if (pageParam.action === 'new') { - // // todo: 附件 - // const newEmail = { to: newToEmail, subject: '' } - // // form.setFieldsValue(newEmail) - // // setInitialContent((contentPrefix || '') + signatureBody) - // } - - // return () => {} - // }, [ mailData.info, signature, newToEmail, contentPrefix]) - const [openPlainTextConfirm, setOpenPlainTextConfirm] = useState(false) const handlePlainTextOpenChange = ({ target }) => { const { value: newChecked } = target @@ -486,18 +362,18 @@ const NewEmail = () => { // 1. ~直接上传返回地址~ // 2. 发送文件信息 const [fileList, setFileList] = useState([]) - const handleChange = (info) => { - let newFileList = [...info.fileList] - // 2. Read from response and show file link - newFileList = newFileList.map((file) => { - if (file.response) { - // Component will show file.url as link - file.url = file.response.url - } - return file - }) - setFileList(newFileList) - } + // const handleChange = (info) => { + // let newFileList = [...info.fileList] + // // 2. Read from response and show file link + // newFileList = newFileList.map((file) => { + // if (file.response) { + // // Component will show file.url as link + // file.url = file.response.url + // } + // return file + // }) + // setFileList(newFileList) + // } const normFile = (e) => { // console.log('Upload event:', e); if (Array.isArray(e)) { @@ -522,7 +398,24 @@ const NewEmail = () => { setFileList((prev) => [...prev, file]) return false // 阻止默认上传, 附件不上传阿里云 }, - onRemove: (file) => { + onRemove: async (file) => { + console.log('onRomove', file) + if (file.fullPath) { + try { + const x = await deleteEmailAttachmentAction([file.uid]); + message.success(`已删除 ${file.name}`, 2) + } catch (error) { + console.error(error) + notification.error({ + key: editorKey, + message: '删除失败', + description: error.message, + placement: 'top', + duration: 3, + }) + return false; + } + } const index = fileList.indexOf(file) const newFileList = fileList.slice() newFileList.splice(index, 1) @@ -569,7 +462,10 @@ const NewEmail = () => { // win.document.write(""); resolve(reader.result) } - if (file.type.startsWith('text/') || file.type === 'application/html' || file.type === 'application/xhtml+xml') { + if (file.fullPath) { + openPopup(file.fullPath, file.uid) + } + else if (file.type.startsWith('text/') || file.type === 'application/html' || file.type === 'application/xhtml+xml') { reader.readAsText(file) } else { reader.readAsDataURL(file) @@ -580,102 +476,65 @@ const NewEmail = () => { }, } - /** - * 保存成功, 推一个气泡 - * 再从异步通知更新消息发送状态 - */ - // 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: stickToCid, - msg_source: 'email', - } - // olog('invoke upload', msgObjMerge) - const contentToRender = sentMsgTypeMapped[msgObjMerge.type].contentToRender(msgObjMerge) - // console.log(contentToRender, 'contentToRender sendMessage------------------'); - // sentOrReceivedNewMessage(contentToRender.conversationid, contentToRender) - } - const [sendLoading, setSendLoading] = useState(false) const onHandleSaveOrSend = async (isDraft = false) => { // console.log('onSend callback', '\nisRichText', isRichText); - console.log(form.getFieldsValue()); + // console.log(form.getFieldsValue()); const body = structuredClone(form.getFieldsValue()) - // body.mailtype = ''; // todo: 邮件类型 - // body.id = ''; // todo: 已保存的草稿 - // body.from = newFromEmail // todo: - body.attaList = fileList - body.opi_sn = emailOPI - body.mat_sn = emailMat - body.coli_sn = emailOrder || '' - // console.log('body', body, '\n', emailOrder); + body.attaList = fileList; + // console.log('body', body, '\n', fileList); const values = await form.validateFields() const preQuoteBody = pageParam.quoteid ? (quoteContent ? quoteContent : generateQuoteContent(mailData, isRichText)) : '' body.mailcontent = isRichText ? EmailBuilder({ subject: values.subject, content: htmlContent + preQuoteBody }) : textContent + preQuoteBody body.cc = values.cc || '' body.bcc = values.bcc || '' - const msgObj = { - type: 'email', - id: uuid(), - from: body.from, - to: values.to, - cc: values.cc || '', - bcc: values.bcc || '', - subject: values.subject, - content: body.mailcontent, - email: { - subject: values.subject, - content: body.mailcontent, - }, - coli_id: orderDetail.order_no || (emailOrder ? `{${emailOrder}}` : ''), - } - setSendLoading(true) + body.bcc = values.mailtype || '' + setSendLoading(!isDraft) + notification.open({ + key: editorKey, + placement: 'top', + // message: '提示', + description: '正在保存...', + duration: 0, + icon: , + closable: false, + }) // body.externalID = stickToCid // body.actionID = `${stickToCid}.${msgObj.id}` body.contenttype = isRichText ? 'text/html' : 'text/plain' try { - const bubbleMsg = cloneDeep(msgObj) - // bubbleMsg.id = `${stickToCid}.${msgObj.id}` - // bubbleMsg.email.mai_sn = ''; - bubbleMsg.content = undefined - // invokeEmailMessage(bubbleMsg); // console.log('postSendEmail', body, '\n', msgObj); // return; // todo: 保存后不在草稿箱, 在待发目录; 传了ID但每次都新增 - const result = await saveEmailDraftOrSendAction(body, isDraft) - const mailSavedId = result.id || '' - bubbleMsg.email.mai_sn = mailSavedId - // console.log('invokeEmailMessage', bubbleMsg); - - // invokeEmailMessage(bubbleMsg) + const mailSavedId = await postEmailSaveOrSend(body, isDraft) + form.setFieldsValue({ + mai_sn: mailSavedId, + id: mailSavedId, + }) + // bubbleMsg.email.mai_sn = mailSavedId // setSendLoading(false); - notification.success({ - key: editorKey, - message: '成功', - // description: error.message, - placement: 'top', - duration: 2, - showProgress: true, - pauseOnHover: true, - onClose: () => { - deleteIndexDBbyKey(editorKey, 'draft', 'mailbox'); - window.close(); - }, - }) + if (!isDraft) { + notification.success({ + key: editorKey, + message: '成功', + description: isDraft ? '' : '窗口将自动关闭...', + placement: 'top', + duration: 2, + showProgress: true, + pauseOnHover: true, + onClose: () => { + deleteIndexDBbyKey(editorKey, 'draft', 'mailbox'); + isDraft ? false : window.close(); + }, + }) + } else { notification.destroy(editorKey) } // setOpen(false) } catch (error) { + console.error(error) notification.error({ key: editorKey, message: '邮件保存失败', @@ -689,9 +548,7 @@ const NewEmail = () => { } const [openDrawerSnippet] = useSnippetStore((state) => [state.openDrawer]) - // const [openPaymentDrawer] = useOrderStore((state) => [state.openDrawer]) - const [bakData, setBakData] = useState({}) const idleCallbackId = useRef(null) const debouncedSave = useCallback( debounce((data) => { @@ -702,13 +559,6 @@ const NewEmail = () => { }, 1500), // 1.5s [], ) - const onEditChange = (changedValues, allValues) => { - console.log('onEditChange', changedValues, '\n', allValues) - // const { name, value } = e.target; - // setBakData(prevData => ({ ...prevData, [name]: value })); - // debouncedSave(bakData); - } - useEffect(() => { return () => { if (idleCallbackId.current && window.cancelIdleCallback) { @@ -716,6 +566,13 @@ const NewEmail = () => { } } }, [debouncedSave]) + const onEditChange = (changedValues, allValues) => { + // console.log('onEditChange', changedValues, '\n', allValues) + if ('from' in changedValues) { + handleSwitchEmail(allValues.from); + } + } + return ( <> @@ -735,14 +592,14 @@ const NewEmail = () => { requiredMark={false} // labelCol={{ span: 3 }} > -
+
- - `发件人: ${item?.label || '选择'}`} variant={'borderless'} placeholder='发件人: 选择' className='[&_.ant-select-selection-item]:font-bold [&_.ant-select-selection-placeholder]:font-bold [&_.ant-select-selection-placeholder]:text-black' classNames={{popup: {root:'min-w-60'}}} /> + {/*
请选择发件地址
*/}
{orderDetail.order_no} {templateContent.mailtypeName} @@ -789,7 +646,7 @@ const NewEmail = () => { - + diff --git a/src/views/orders/Follow.jsx b/src/views/orders/Follow.jsx index b277957..8dfe200 100644 --- a/src/views/orders/Follow.jsx +++ b/src/views/orders/Follow.jsx @@ -114,7 +114,7 @@ function Follow() { subject: emailItem.MAI_Subject, }, } - console.log('emailItem', emailItem); + // console.log('emailItem', emailItem); setSelectedEmail(emailMsg) }; diff --git a/src/views/orders/components/NewEmailButton.jsx b/src/views/orders/components/NewEmailButton.jsx index 526c4bb..eb69f70 100644 --- a/src/views/orders/components/NewEmailButton.jsx +++ b/src/views/orders/components/NewEmailButton.jsx @@ -1,8 +1,7 @@ -import { createContext, useEffect, useMemo, useState } from 'react' -import { App, Flex, Button, Tooltip, List, Form, Row, Col, Dropdown, Input, Checkbox, DatePicker, Switch, Breadcrumb, Skeleton } from 'antd' +import { useMemo } from 'react' +import { App, Dropdown } from 'antd' import useConversationStore from '@/stores/ConversationStore' -import { emailTemplates, openPopup, useEmailTemplate } from '@/hooks/useEmail'; -import { POPUP_FEATURES } from '@/config'; +import { emailTemplates, openPopup } from '@/hooks/useEmail'; import { isEmpty } from '@/utils/commons'; const NewEmailButton = ({ ...props }) => { @@ -15,12 +14,12 @@ const NewEmailButton = ({ ...props }) => { notification.warning({ message: '请选择到订单目录', placement: 'top' }) return false } - openPopup(`/email/new/0/${COLI_SN}/${key}`, `new-0-${COLI_SN}-${key}`, POPUP_FEATURES) + openPopup(`/email/new/0/${COLI_SN}/${key}`, `new-0-${COLI_SN}-${key}`) }; const handleNewEmail = () => { console.info('新邮件') - openPopup(`/email/new/0/${COLI_SN}`, `new-0-${COLI_SN}`, POPUP_FEATURES) + openPopup(`/email/new/0/${COLI_SN}`, `new-0-${COLI_SN}`) } return (