dev/ckeditor
Lei OT 4 days ago
parent 1c60330d2e
commit c099bb77cd

@ -1,4 +1,4 @@
import React, { useState, useEffect, useRef } from 'react'
import React, { useState, useEffect, useRef, useCallback } from 'react'
import { CKEditor } from 'ckeditor4-react'
const App = ({ initData = '' }) => {
@ -7,7 +7,7 @@ const App = ({ initData = '' }) => {
const editorRef = useRef(null)
useEffect(() => {
// setEditorData(initData)
setEditorData(initData)
console.log('🔔🔔New content on useEffect.')
console.log(initData.length)
if (editorRef.current) {
@ -32,14 +32,14 @@ const App = ({ initData = '' }) => {
}
const handleInstanceReady = ({ editor }) => {
console.log('CKEditor 4 instance is ready:', editor)
console.log('🔰CKEditor 4 instance is ready:', editor)
editorRef.current = editor // Store the editor instance in a ref
// if (editorRef.current) {
requestAnimationFrame(() => {
editor.setData(initData)
// setEditorData(initData) // Also update our React state to reflect the change
console.log('🔔New content set after editor was ready.')
console.log(initData.length)
editor.setData(editorData)
// // setEditorData(initData) // Also update our React state to reflect the change
console.log('🔔New content set after editor was ready.\n', initData.length)
// console.log(initData.length)
})
// }
}
@ -59,7 +59,7 @@ const App = ({ initData = '' }) => {
{window.CKEDITOR && window.CKEDITOR.version && (
<div className='mb-6'>
<label htmlFor='editor' className='block text-gray-700 text-lg font-medium mb-2'></label>
<CKEditor
<CKEditor key={'email-editor'}
editor={window.CKEDITOR}
// data={editorData} // Initial data for the editor
initData={editorData}
@ -70,10 +70,10 @@ const App = ({ initData = '' }) => {
versionCheck: false,
removePlugins: 'elementspath,save,exportpdf,newpage,print,templates,pagebreak,about,forms,iframe',
// removeButtons: 'Source',
height: '460px',
height: '600px',
type: 'inline',
extraPlugins: 'autogrow',
// autoGrow_minHeight: 480,
autoGrow_minHeight: 400,
// autoGrow_maxHeight: 1000,
// defaultLanguage: 'zh-cn',
language: 'zh-cn',

@ -2,12 +2,11 @@ import { useEffect, useState, useRef, useCallback, useMemo } from 'react'
import { useParams, useNavigate, useLocation } from 'react-router-dom';
import { App, ConfigProvider, Button, Form, Input, Flex, Checkbox, Popconfirm, Select, Space, Upload, Divider, Modal, Tabs, Radio, Typography } from 'antd'
import { UploadOutlined, LoadingOutlined, SaveOutlined, SendOutlined, CheckCircleOutlined } from '@ant-design/icons'
import '@dckj/react-better-modal/dist/index.css'
import useStyleStore from '@/stores/StyleStore'
// import useConversationStore from '@/stores/ConversationStore'
import useAuthStore from '@/stores/AuthStore'
import LexicalEditor from '@/components/LexicalEditor'
// import LexicalEditor from '@/components/LexicalEditor'
import { v4 as uuid } from 'uuid'
import { cloneDeep, debounce, isEmpty, olog, omitEmpty } from '@/utils/commons'
@ -24,7 +23,7 @@ import { TextIcon } from '@/components/Icons';
import { EMAIL_ATTA_HOST, POPUP_FEATURES } from '@/config';
import CKEditor from '@/components/CKEditor';
const {confirm} = Modal;
//
// .application, .exe, .app
const disallowedAttachmentTypes = [
@ -48,30 +47,33 @@ const parseHTMLText = (html) => {
const parser = new DOMParser()
const dom = parser.parseFromString(html, 'text/html')
// Replace <br> and <p> with line breaks
Array.from(dom.body.querySelectorAll('br, p')).forEach((el) => {
el.textContent = '\n' + el.textContent
})
// Array.from(dom.body.querySelectorAll('br, p')).forEach((el) => {
// el.textContent = '<br>' + el.textContent
// })
// Replace <hr> with a line of dashes
Array.from(dom.body.querySelectorAll('hr')).forEach((el) => {
el.textContent = '\n------------------------------------------------------------------\n'
})
return dom.body.textContent || ''
// Array.from(dom.body.querySelectorAll('hr')).forEach((el) => {
// el.innerHTML = '<p><hr>------------------------------------------------------------------</p>'
// })
const line = '<p>------------------------------------------------------------------</p>'
return line+(dom.body.innerHTML || '')
}
const generateQuoteContent = (mailData, isRichText = true) => {
const html = `<br><hr><p class="font-sans"><b><strong >From: </strong></b><span >${(mailData.info?.MAI_From || '')
// const { bodyContent } = parseHTMLString(mailData.content);
const html = `<br><hr><blockquote><p class="font-sans"><b><strong >From: </strong></b><span >${(mailData.info?.MAI_From || '')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')} </span></p><p class="font-sans"><b><strong >Sent: </strong></b><span >${
mailData.info?.MAI_SendDate || ''
}</span></p><p class="font-sans"><b><strong >To: </strong></b><span >${(mailData.info?.MAI_To || '')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')}</span></p><p class="font-sans"><b><strong >Subject: </strong></b><span >${mailData.info?.MAI_Subject || ''}</span></p><p>${
mailData.info?.MAI_ContentType === 'text/html' ? mailData.content : mailData.content.replace(/\r\n/g, '<br>')
}</p>`
.replace(/>/g, '&gt;')}</span></p><p class="font-sans"><b><strong >Subject: </strong></b><span >${mailData.info?.MAI_Subject || ''}</span></p>${
mailData.info?.MAI_ContentType === 'text/html' ? parseHTMLString(mailData.content) : mailData.content.replace(/\r\n/g, '<br>')
}</blockquote>`
// console.log('📃', html)
return isRichText ? html : parseHTMLText(html)
}
const generateMailContent = (mailData) => `${mailData.content}<br>`
const generateMailContent = (mailData) => mailData.info?.MAI_ContentType === 'text/html' ? `${mailData.content}<br>` : `<p>${mailData.content.replace(/\r\n/g, '<br>')}</p>`
/**
* 独立窗口编辑器
@ -173,7 +175,7 @@ const NewEmail = () => {
useEffect(() => {
// console.log('useEffect 1---- \nform.setFieldsValue ');
if (isEmpty(mailData.content) && isEmpty(orderDetail.order_no)) {
return () => {}
// return () => {}
}
const docTitle = mailData.info?.MAI_Subject || 'New Email-';
document.title = docTitle
@ -199,9 +201,11 @@ const NewEmail = () => {
const _form2 = {
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 || '',
mat_sn: emailAccount?.mat_sn || info?.MAI_MAT_SN || defaultMAT,
opi_sn: emailAccount?.opi_sn || info?.MAI_OPI_SN || orderDetail.opi_sn || '',
}
const originalContentType = info?.mailType === 'text/html';
setIsRichText(originalContentType)
let readyToInitialContent = '';
let _formValues = {};
@ -216,7 +220,7 @@ const NewEmail = () => {
// 稿: ``id
if (!isEmpty(mailData.info) && !['edit'].includes(pageParam.action)) {
readyToInitialContent = orderPrefix + signatureBody
readyToInitialContent = orderPrefix + '<br>' + signatureBody
}
switch (pageParam.action) {
case 'reply':
@ -228,6 +232,7 @@ const NewEmail = () => {
subject: `Re: ${info.MAI_Subject || ''}`,
..._form2
}
readyToInitialContent += generateQuoteContent(mailData, originalContentType)
break
case 'replyall':
_formValues = {
@ -238,6 +243,7 @@ const NewEmail = () => {
subject: `Re: ${info.MAI_Subject || ''}`,
..._form2
}
readyToInitialContent += generateQuoteContent(mailData, originalContentType)
break
case 'forward':
_formValues = {
@ -246,6 +252,7 @@ const NewEmail = () => {
// coli_sn: pageParam.oid,
..._form2
}
readyToInitialContent += generateQuoteContent(mailData, originalContentType)
break
case 'edit':
_formValues = {
@ -257,7 +264,7 @@ const NewEmail = () => {
mai_sn: pageParam.quoteid,
..._form2
}
readyToInitialContent = '<br>'+ generateMailContent(mailData)
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':
@ -268,8 +275,9 @@ const NewEmail = () => {
subject: `${info.MAI_Subject || templateFormValues.subject || ''}`,
..._form2,
}
readyToInitialContent = generateMailContent({ content: templateContent.bodycontent || readyToInitialContent || '' })
setFileList(mailData.attachments.map(ele => ({ uid: ele.ATI_SN, name: ele.ATI_Name, url: ele.ATI_ServerFile, fullPath: `${EMAIL_ATTA_HOST}${ele.ATI_ServerFile}` })))
readyToInitialContent = generateMailContent({ content: templateContent.bodycontent || readyToInitialContent || `<p></p><br>${signatureBody}` || '' })
// setFileList(mailData.attachments.map(ele => ({ uid: ele.ATI_SN, name: ele.ATI_Name, url: ele.ATI_ServerFile, fullPath: `${EMAIL_ATTA_HOST}${ele.ATI_ServerFile}` })))
setIsRichText(true)
break
default:
@ -280,7 +288,7 @@ const NewEmail = () => {
setInitialContent(readyToInitialContent);
return () => {}
}, [orderDetail.order_no, quoteLoading, loadingTamplate, emailAccountOPI, signature])
}, [orderDetail.order_no, quoteLoading, loadingTamplate, emailAccount, signature])
// const readFromTemplate = () => {
@ -327,7 +335,7 @@ const NewEmail = () => {
// const _findMat = emailListAddrMapped?.[value]
// setEmailMat(_findMat?.mat_sn)
// setEmailOPI(_findMat?.opi_sn)
console.log(_findMat, 'handleSwitchEmail')
// console.log(_findMat, 'handleSwitchEmail')
setEmailAccount(_findMat)
setEmailAccountOPI(_findMat?.opi_sn)
}
@ -347,12 +355,14 @@ const NewEmail = () => {
}
const handleEditorChange = ({ editorStateJSON, htmlContent, textContent }) => {
// console.log('textContent', textContent);
const _text = textContent.replace(/\r\n/g, '\n').replace(/\n{2,}/g, '\n')
// console.log('textContent---\n', textContent, 'textContent');
// console.log('html', html);
setHtmlContent(htmlContent)
setTextContent(textContent)
setTextContent(_text)
form.setFieldValue('content', htmlContent)
const { bodyText: abstract } = parseHTMLString(htmlContent, true);
const abstract = _text;
// const { bodyText: abstract } = parseHTMLString(htmlContent, true);
// form.setFieldValue('abstract', getAbstract(textContent))
const formValues = omitEmpty(form.getFieldsValue());
if (!isEmpty(formValues)) {
@ -502,8 +512,8 @@ const NewEmail = () => {
body.attaList = fileList;
// console.log('body', body, '\n', fileList);
const values = await form.validateFields()
const preQuoteBody = !['edit', 'new'].includes(pageParam.action) && pageParam.quoteid ? (quoteContent ? quoteContent : generateQuoteContent(mailData, isRichText)) : ''
body.mailcontent = isRichText ? EmailBuilder({ subject: values.subject, content: htmlContent + preQuoteBody }) : textContent + preQuoteBody
// const preQuoteBody = !['edit', 'new'].includes(pageParam.action) && pageParam.quoteid ? (quoteContent ? quoteContent : generateQuoteContent(mailData, isRichText)) : ''
body.mailcontent = isRichText ? EmailBuilder({ subject: values.subject, content: htmlContent }) : textContent
body.cc = values.cc || ''
body.bcc = values.bcc || ''
body.bcc = values.mailtype || ''
@ -522,7 +532,9 @@ const NewEmail = () => {
body.contenttype = isRichText ? 'text/html' : 'text/plain'
try {
// console.log('postSendEmail', body, '\n', msgObj);
// console.log('postSendEmail', body, '\n');
// console.log('🎈postSendEmail mailContent', body.mailcontent, '\n');
// throw new Error('test')
// return;
const mailSavedId = await postEmailSaveOrSend(body, isDraft)
form.setFieldsValue({
@ -609,7 +621,7 @@ const NewEmail = () => {
// labelCol={{ span: 3 }}
>
<div className='w-full flex flex-wrap gap-2 justify-start items-center text-indigo-600 pb-1 mb-2 border-x-0 border-t-0 border-b border-solid border-neutral-200'>
<Button type='primary' size='middle' onClick={onHandleSaveOrSend} loading={sendLoading} icon={<SendOutlined />}>
<Button type='primary' size='middle' onClick={() => onHandleSaveOrSend()} loading={sendLoading} icon={<SendOutlined />}>
发送
</Button>
<Form.Item name={'from'} rules={[{ required: true, message: '请选择发件地址' }]} >
@ -710,14 +722,14 @@ const NewEmail = () => {
</Form>
<CKEditor initData={initialContent} />
{/* <LexicalEditor {...{ isRichText }} onChange={handleEditorChange} defaultValue={initialContent} /> */}
{!isEmpty(Number(pageParam.quoteid)) && pageParam.action!=='edit' && !showQuoteContent && (
{/* {!isEmpty(Number(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)}>
显示引用内容 {/*(不可更改)*/}
<Button className='flex gap-2 ' type='link' onClick={() => {
setShowQuoteContent(!showQuoteContent);
setInitialContent(pre => pre + generateQuoteContent(mailData))
}}>
显示引用内容
</Button>
{/* <Button className='flex gap-2 ' type='link' danger onClick={() => {setMergeQuote(false);setShowQuoteContent(false)}}>
删除引用内容
</Button> */}
</div>
)}
{showQuoteContent && (
@ -726,7 +738,7 @@ const NewEmail = () => {
className='border-0 outline-none cursor-text'
onBlur={(e) => setQuoteContent(`<blockquote>${e.target.innerHTML}</blockquote>`)}
dangerouslySetInnerHTML={{ __html: generateQuoteContent(mailData) }}></blockquote>
)}
)} */}
</ConfigProvider>
</>
)

Loading…
Cancel
Save