提交 a29212a5 authored 作者: 王鹏飞's avatar 王鹏飞

chore: update

上级 17692dfa
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react'
import { Modal, Divider, Upload, Input, Space, Button, Form, Spin, message, ColorPicker, Select, InputNumber, Row, Col } from 'antd'
import { DomEditor, SlateEditor, SlateTransforms, SlateElement } from '@wangeditor/editor'
import { useState, useEffect, forwardRef } from 'react'
import { Divider, Input, Space, Button, Form, ColorPicker, Select, InputNumber, Row, Col } from 'antd'
import { SlateEditor, SlateTransforms, SlateElement } from '@wangeditor/editor'
import { fontFamilyList, fontSizeList } from '../utils/setting'
import $ from 'jquery'
import './index.less'
const ChapterItemModal = forwardRef((props, ref) => {
const ChapterItemModal = (props, ref) => {
const { editor, setSectionInfo, sectionInfo, setSectionVisible } = props
const [form] = Form.useForm()
const [visible, setVisible] = useState(false)
// 是否更新的判断
const [toolStatus, setToolStatus] = useState(false)
const [bgColorValue, setBgColorValue] = useState('#000000')
const [textColor, setTextColor] = useState('#ffffff')
const [nowRandom, setNowRandom] = useState(null)
......@@ -25,12 +22,6 @@ const ChapterItemModal = forwardRef((props, ref) => {
family: '黑体'
})
useImperativeHandle(ref, () => {
return {
setVisible
}
})
useEffect(() => {
if (sectionInfo && Object.entries(sectionInfo).length > 0) {
setInitValues({ ...sectionInfo })
......@@ -60,24 +51,9 @@ const ChapterItemModal = forwardRef((props, ref) => {
height: height,
size: size
})
setToolStatus(true)
setNowRandom(random)
}
// 获取当前节点的上一个节点
function getPreviousNode(editor) {
const { selection } = editor
if (!selection) return null
const [start] = SlateEditor.nodes(editor, { at: selection })
const previous = SlateEditor.previous(editor, { at: start[1] })
if (previous) {
return previous
}
return null
}
const onFinish = values => {
editor.restoreSelection()
const nodeEntries = SlateEditor.nodes(editor, {
......@@ -129,11 +105,7 @@ const ChapterItemModal = forwardRef((props, ref) => {
return
}
const html = editor.getHtml()
const parser = new DOMParser()
let random = Math.random().toString(10).substring(2, 10)
const docBody = parser.parseFromString(html, 'text/html')
const section = docBody.body.querySelectorAll('.chapter-item-section') // 节头标签
editor.insertNode({
type: 'chapterSection',
......@@ -217,14 +189,6 @@ const ChapterItemModal = forwardRef((props, ref) => {
})}
</Select>
</Form.Item>
{/* <InputNumber
controls={false}
min={10}
placeholder=''
style={{ width: '100%', textAlign: 'left' }}
allowClear
/> */}
</Col>
<Col span={12}>
<Form.Item label="对齐方式" name="align" rules={[{ required: true, message: '请选择对齐方式' }]}>
......@@ -257,6 +221,6 @@ const ChapterItemModal = forwardRef((props, ref) => {
</div>
</div>
)
})
}
export default ChapterItemModal
export default forwardRef(ChapterItemModal)
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react'
import { Modal, Divider, Upload, Input, Space, Button, Form, Spin, message, ColorPicker, Select, InputNumber, Row, Col } from 'antd'
import { useState, useEffect, forwardRef, useImperativeHandle } from 'react'
import { Divider, Upload, Input, Space, Button, Form, Spin, message, ColorPicker, Select, InputNumber, Row, Col } from 'antd'
import { CloudUploadOutlined } from '@ant-design/icons'
import { DomEditor, SlateEditor, SlateTransforms, SlateElement } from '@wangeditor/editor'
import { SlateEditor, SlateTransforms, SlateElement } from '@wangeditor/editor'
import { fontFamilyList, fontSizeList } from '../utils/setting'
import './index.less'
import $ from 'jquery'
import { partSize, normalUploader, multipartUploader } from '../utils/upload'
import { uploadFile } from '@/utils/oss'
const { Dragger } = Upload
const imgUrl2 = 'http://zxts-book-file.zijingebook.com/2024/03/05/image-1709606013683-6k5qmzf75zj.png'
const ImageModal = forwardRef((props, ref) => {
const { editor, ossClient, setTitleVisible, titleInfo, setTitleInfo } = props
const ImageModal = (props, ref) => {
const { editor, setTitleVisible, titleInfo, setTitleInfo } = props
const fileAccept = ['.png', '.jpg', '.jpeg', '.svg']
const [form] = Form.useForm()
......@@ -22,7 +19,6 @@ const ImageModal = forwardRef((props, ref) => {
const [uploading, setUploading] = useState(false) // 文件上传状态
const [progress, setProgress] = useState(0)
const [file, setFile] = useState({})
const [fileList, setFileList] = useState([])
const [imgUrl, setImgUrl] = useState('')
const [initValues, setInitValues] = useState({
title: '',
......@@ -81,45 +77,25 @@ const ImageModal = forwardRef((props, ref) => {
setNowRandom(random)
}
const normFile = e => {
if (Array.isArray(e)) {
return e
}
return e?.fileList
}
const uploadProps = {
name: 'file',
maxCount: 1,
showUploadList: false,
accept: fileAccept.join(','),
beforeUpload: (file, fileList) => {
beforeUpload: file => {
const fileExt = file.name.substring(file.name.lastIndexOf('.'))
if (!fileAccept.includes(fileExt.toLowerCase())) {
message.error('请上传正确格式的图片')
return false
}
setFile(file)
setFileList(fileList)
},
customRequest: async () => {
setUploading(true)
let data = null
if (file.size >= partSize) {
data = await multipartUploader(file, 'image', ossClient, (progress, checkpoint) => {
console.log(`上传进度 ${progress}`)
setProgress(parseInt(progress * 100))
})
console.log('multipartUploader --> ', data)
} else {
data = await normalUploader(file, 'image', ossClient)
console.log('normalUploader --> ', data)
}
const url = await uploadFile(file)
if (data.status === 200 && data.statusCode === 200) {
const { url, name } = data
setImgUrl(url)
form.setFieldsValue({ bgImgUrl: url })
}
setImgUrl(url)
form.setFieldsValue({ bgImgUrl: url })
setUploading(false)
}
}
......@@ -139,7 +115,7 @@ const ImageModal = forwardRef((props, ref) => {
universal: true
})
for (let nodeEntry of nodeEntries) {
const [node, path] = nodeEntry
const [node] = nodeEntry
if (node.children[0].text === '') {
SlateTransforms.removeNodes(editor)
}
......@@ -211,7 +187,7 @@ const ImageModal = forwardRef((props, ref) => {
<Divider />
<div className="editor-content-form">
<Form layout="vertical" name="validate_other" form={form} onFinish={onFinish} initialValues={initValues}>
<Form.Item label="章头背景图片" valuePropName="fileList" getValueFromEvent={normFile} name="bgImgUrl">
<Form.Item label="章头背景图片" name="bgImgUrl">
<Spin spinning={uploading} tip={`${progress}%`}>
<div className="editor-dragger">
<Dragger {...uploadProps} showUploadList={false}>
......@@ -351,6 +327,6 @@ const ImageModal = forwardRef((props, ref) => {
</div>
</div>
)
})
}
export default ImageModal
export default forwardRef(ImageModal)
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react';
import { Modal, Divider, Space, Button, message } from 'antd';
import { SlateTransforms, SlateEditor, DomEditor, SlateElement } from '@wangeditor/editor';
import { useState, useEffect, forwardRef, useImperativeHandle } from 'react'
import { Modal, Divider, Space, Button, message } from 'antd'
// import formulaEditor from 'easy-formula-editor';
import './index.less';
import './index.less'
const FormulaModal = forwardRef((props, ref) => {
const { editor, ossClient } = props;
const [visible, setVisible] = useState(false);
const [editor2, setEditor2] = useState(null);
const FormulaModal = (props, ref) => {
const { editor } = props
const [visible, setVisible] = useState(false)
const [editor2, setEditor2] = useState(null)
useImperativeHandle(ref, () => {
return {
setVisible,
};
});
setVisible
}
})
useEffect(() => {
if (visible) {
setTimeout(() => {
const editor2 = new formulaEditor();
const editor2 = new formulaEditor()
// 增加预设公式
// editor2.menusConfig.presets.push({ label: '勾股定理', value: 'a^2+b^2=c^2' });
editor2.config.width = '900px';
editor2.create('#test');
setEditor2(editor2);
}, 500);
editor2.config.width = '900px'
editor2.create('#test')
setEditor2(editor2)
}, 500)
} else {
editor2 && editor2.destoryDom();
editor2 && editor2.destoryDom()
}
}, [visible]);
}, [visible])
const insertFormula = () => {
editor.restoreSelection();
editor.restoreSelection()
// latex 公式
// console.log(editor2.latex.text());
// html 公式
// console.log(editor2.$textSvgElem.html());
const html = editor2.$textSvgElem.html();
const html = editor2.$textSvgElem.html()
if (html) {
// editor
editor.insertNode({
type: 'chapterFormula',
formulaHtml: html,
children: [{ text: '' }],
});
setVisible(false);
children: [{ text: '' }]
})
setVisible(false)
} else {
message.error('请选择公式内容!');
message.error('请选择公式内容!')
}
};
}
return (
<div>
......@@ -58,33 +57,32 @@ const FormulaModal = forwardRef((props, ref) => {
footer={null}
centered
destroyOnClose
title='公式'
title="公式"
classNames={{
header: 'editor-header-customer',
body: 'editor-body-customer',
wrapper: 'editor-wrapper-customer',
wrapper: 'editor-wrapper-customer'
}}
maskClosable={false}
onCancel={() => setVisible(false)}
width='900px'
>
width="900px">
<Divider />
<div className='formula-container'>
<div id='test'></div>
<div className="formula-container">
<div id="test"></div>
</div>
<div className='formula-buttons'>
<div className="formula-buttons">
<Space>
<Button type='default' onClick={() => setVisible(false)}>
<Button type="default" onClick={() => setVisible(false)}>
取消
</Button>
<Button type='primary' onClick={insertFormula}>
<Button type="primary" onClick={insertFormula}>
插入公式
</Button>
</Space>
</div>
</Modal>
</div>
);
});
)
}
export default FormulaModal;
export default forwardRef(FormulaModal)
......@@ -9,7 +9,7 @@ import GalleryFormItem from './galleryItem'
const randomOne = Math.random().toString(16).substring(2, 10)
const GalleryModal = props => {
const { editor, ossClient, galleryInfo, bookId, chapterId, setGalleryVisible, setGalleryInfo, selectionSize = 18, isOnline = false } = props
const { editor, galleryInfo, bookId, chapterId, setGalleryVisible, setGalleryInfo, selectionSize = 18, isOnline = false } = props
const [form] = Form.useForm()
const [loading, setLoading] = useState(false)
......@@ -47,9 +47,7 @@ const GalleryModal = props => {
const initialItems = [
{
label: '图 1',
children: (
<GalleryFormItem ossClient={ossClient} form={form} galleryInfo={galleryInfo} activeKey={randomOne} setPicList={setPicList} isOnline={isOnline} />
),
children: <GalleryFormItem form={form} galleryInfo={galleryInfo} activeKey={randomOne} setPicList={setPicList} isOnline={isOnline} />,
key: randomOne,
forceRender: true
}
......@@ -68,9 +66,7 @@ const GalleryModal = props => {
const newActiveKey = `${random}`
newPanes.push({
label: `图 ${index + 1}`,
children: (
<GalleryFormItem ossClient={ossClient} form={form} galleryInfo={galleryInfo} activeKey={newActiveKey} setPicList={setPicList} isOnline={isOnline} />
),
children: <GalleryFormItem form={form} galleryInfo={galleryInfo} activeKey={newActiveKey} setPicList={setPicList} isOnline={isOnline} />,
key: newActiveKey,
forceRender: true
})
......@@ -163,7 +159,6 @@ const GalleryModal = props => {
label: `图 ${index + 1}`,
children: (
<GalleryFormItem
ossClient={ossClient}
galleryInfo={{ ...galleryInfo, galleryList: encodeURI(JSON.stringify(galleryArr)) }}
form={form}
setPicList={setPicList}
......
import { useState, useEffect, useImperativeHandle, forwardRef } from 'react'
import { CloudUploadOutlined } from '@ant-design/icons'
import { Form, Input, Spin, Upload, Button } from 'antd'
import { partSize, normalUploader, multipartUploader } from '../utils/upload'
import OnlineImageList from './onlineImageList'
import { uploadFile } from '@/utils/oss'
const fileAccept = ['.png', '.jpg', '.jpeg', '.svg']
const randomOne = Math.random().toString(16).substring(2, 10)
const GalleryFormItem = (props, ref) => {
const { activeKey, ossClient, form, setPicList, galleryInfo, isOnline = false } = props
const { activeKey, form, setPicList, galleryInfo, isOnline = false } = props
const [uploading, setUploading] = useState(false) // 文件上传状态
const [progress, setProgress] = useState(0)
const [file, setFile] = useState({})
const [fileList, setFileList] = useState([])
const [imgUrl, setImgUrl] = useState('')
useImperativeHandle(ref, () => {
......@@ -36,7 +34,7 @@ const GalleryFormItem = (props, ref) => {
if (galleryArr.length > 0) {
const values = { ['content']: {} }
galleryArr.forEach((item) => {
galleryArr.forEach(item => {
values['content'][item.key] = {
url: item.url,
title: item.title,
......@@ -45,7 +43,7 @@ const GalleryFormItem = (props, ref) => {
})
form.setFieldsValue({ ...values, gallery: galleryArr })
const item = galleryArr.filter((item) => item.key === activeKey)
const item = galleryArr.filter(item => item.key === activeKey)
if (item.length > 0) {
const itemGallery = item[0]
setImgUrl(itemGallery.url)
......@@ -56,69 +54,41 @@ const GalleryFormItem = (props, ref) => {
useEffect(() => {}, [])
const normFile = (e) => {
if (Array.isArray(e)) {
return e
}
return e?.fileList
}
const uploadProps = {
name: 'file',
maxCount: 1,
showUploadList: false,
accept: fileAccept.join(','),
beforeUpload: (file, fileList) => {
const fileExt = file.name.substring(file.name.lastIndexOf('.'))
if (!fileAccept.includes(fileExt.toLowerCase())) {
message.error('请上传正确格式的图片')
return false
}
beforeUpload: file => {
setFile(file)
setFileList(fileList)
},
customRequest: async () => {
setUploading(true)
let data = null
if (file.size >= partSize) {
data = await multipartUploader(file, 'gallery', ossClient, (progress, checkpoint) => {
console.log(`上传进度 ${progress}`)
setProgress(parseInt(progress * 100))
})
console.log('multipartUploader --> ', data)
} else {
data = await normalUploader(file, 'gallery', ossClient)
console.log('normalUploader --> ', data)
}
if (data.status === 200 && data.statusCode === 200) {
const { url, name } = data
const filename = file.name.substring(0, file.name.lastIndexOf('.'))
const values = {
['content']: {
[activeKey]: {
url: url,
title: '',
desc: ''
}
const url = await uploadFile(file)
const values = {
['content']: {
[activeKey]: {
url: url,
title: '',
desc: ''
}
}
setImgUrl(url)
form.setFieldsValue({ ...values })
const allContent = form.getFieldValue('content')
const newGalleryList = []
// eslint-disable-next-line guard-for-in
for (let key in allContent) {
newGalleryList.push({ ...allContent[key], key: key })
}
setPicList(newGalleryList)
form.setFieldsValue({ gallery: newGalleryList })
}
setImgUrl(url)
form.setFieldsValue({ ...values })
const allContent = form.getFieldValue('content')
const newGalleryList = []
// eslint-disable-next-line guard-for-in
for (let key in allContent) {
newGalleryList.push({ ...allContent[key], key: key })
}
setPicList(newGalleryList)
form.setFieldsValue({ gallery: newGalleryList })
setUploading(false)
}
}
const changeTitleValue = (e) => {
const changeTitleValue = e => {
const allContent = form.getFieldValue('content')
const newGalleryList = []
// eslint-disable-next-line guard-for-in
......@@ -128,7 +98,7 @@ const GalleryFormItem = (props, ref) => {
setPicList(newGalleryList)
form.setFieldsValue({ gallery: newGalleryList })
}
const changeDescValue = (e) => {
const changeDescValue = e => {
const allContent = form.getFieldValue('content')
const newGalleryList = []
// eslint-disable-next-line guard-for-in
......@@ -139,7 +109,7 @@ const GalleryFormItem = (props, ref) => {
form.setFieldsValue({ gallery: newGalleryList })
}
const onOnlineImageChange = (url) => {
const onOnlineImageChange = url => {
setImgUrl(url)
const values = {
['content']: {
......@@ -165,23 +135,11 @@ const GalleryFormItem = (props, ref) => {
return (
<>
{isOnline ? (
<Form.Item
label="在线图片"
valuePropName="fileList"
getValueFromEvent={normFile}
extra="最多可上传10张"
name={['content', activeKey, 'url']}
rules={[{ required: true, message: '请选择图片' }]}>
<Form.Item label="在线图片" extra="最多可上传10张" name={['content', activeKey, 'url']} rules={[{ required: true, message: '请选择图片' }]}>
<OnlineImageList imgUrl={imgUrl} onChange={onOnlineImageChange}></OnlineImageList>
</Form.Item>
) : (
<Form.Item
label="上传图片"
valuePropName="fileList"
getValueFromEvent={normFile}
extra="最多可上传10张"
name={['content', activeKey, 'url']}
rules={[{ required: true, message: '请上传画廊图片' }]}>
<Form.Item label="上传图片" extra="最多可上传10张" name={['content', activeKey, 'url']} rules={[{ required: true, message: '请上传画廊图片' }]}>
<Spin spinning={uploading} tip="Loading">
<div className="editor-dragger">
<Upload.Dragger {...uploadProps} showUploadList={false}>
......
......@@ -5,12 +5,12 @@ import { SlateTransforms, SlateEditor, SlateElement } from '@wangeditor/editor'
import './index.less'
import OnlineImageList from './onlineImageList'
import { partSize, normalUploader, multipartUploader } from '../utils/upload'
import { uploadFile } from '@/utils/oss'
const { Dragger } = Upload
const ImageModal = (props, ref) => {
const { editor, ossClient, setImageVisible, imageInfo, setImageInfo, isOnline = false } = props
const { editor, setImageVisible, imageInfo, setImageInfo, isOnline = false } = props
const [imgUrl, setImgUrl] = useState('')
const fileAccept = ['.png', '.jpg', '.jpeg', '.svg']
......@@ -18,62 +18,39 @@ const ImageModal = (props, ref) => {
const [uploading, setUploading] = useState(false) // 文件上传状态
const [progress, setProgress] = useState(0)
const [file, setFile] = useState({})
const [fileList, setFileList] = useState([])
const [initValues, setInitValues] = useState({ imgUrl: '', imgTitle: '', imgDescript: '' })
const [tempNodeInfo, setTempNodeInfo] = useState(null)
useEffect(() => {
if (imageInfo && Object.entries(imageInfo).length > 0) {
const { image, node } = imageInfo
const { image } = imageInfo
setImgUrl(image.src)
setInitValues({ imgUrl: image.src, imgTitle: image.alt, imgDescript: image.href })
form.setFieldsValue({ imgUrl: image.src, imgTitle: image.alt, imgDescript: image.href })
setTempNodeInfo(imageInfo)
setFile({})
setFileList([])
setImageInfo({})
}
}, [imageInfo])
const normFile = (e) => {
if (Array.isArray(e)) {
return e
}
return e?.fileList
}
const uploadProps = {
name: 'file',
maxCount: 1,
showUploadList: false,
accept: fileAccept.join(','),
beforeUpload: (file, fileList) => {
beforeUpload: file => {
const fileExt = file.name.substring(file.name.lastIndexOf('.'))
if (!fileAccept.includes(fileExt.toLowerCase())) {
message.error('请上传正确格式的图片')
return false
}
setFile(file)
setFileList(fileList)
},
customRequest: async () => {
setUploading(true)
let data = null
if (file.size >= partSize) {
data = await multipartUploader(file, 'image', ossClient, (progress, checkpoint) => {
console.log(`上传进度 ${progress}`)
setProgress(parseInt(progress * 100))
})
console.log('multipartUploader --> ', data)
} else {
data = await normalUploader(file, 'image', ossClient)
console.log('normalUploader --> ', data)
}
if (data.status === 200 && data.statusCode === 200) {
const { url, name } = data
setImgUrl(url)
form.setFieldsValue({ imgUrl: url })
}
const url = await uploadFile(file)
setImgUrl(url)
form.setFieldsValue({ imgUrl: url })
setUploading(false)
}
}
......@@ -88,19 +65,12 @@ const ImageModal = (props, ref) => {
setImageVisible(false)
}
const onFinish = (values) => {
const onFinish = values => {
console.log(values)
editor.restoreSelection()
// editor.insertNode({
// type: 'chapterImage',
// title: values.imgTitle,
// imgUrl: values.imgUrl,
// imgDescript: values.imgDescript,
// children: [{ text: '' }],
// });
const nodeEntries = SlateEditor.nodes(editor, {
match: (node) => {
match: node => {
// JS syntax
if (SlateElement.isElement(node)) {
if (node.type === 'paragraph') {
......@@ -112,7 +82,7 @@ const ImageModal = (props, ref) => {
universal: true
})
for (let nodeEntry of nodeEntries) {
const [node, path] = nodeEntry
const [node] = nodeEntry
if (node.children[0].text === '') {
SlateTransforms.removeNodes(editor)
}
......@@ -142,20 +112,6 @@ const ImageModal = (props, ref) => {
if (tempNodeInfo && Object.entries(tempNodeInfo).length > 0) {
const elem = editor.toDOMNode(tempNodeInfo.node) // 返回 HTMLElement
let nodeProps = JSON.parse(JSON.stringify(tempNodeInfo.node))
let obj = {}
let cIndex = -1
nodeProps.children.forEach((element, index) => {
if (element.type === 'image') {
obj = {
...element,
alt: values.imgTitle,
src: values.imgUrl,
href: values.imgDescript
}
cIndex = index
}
})
SlateTransforms.removeNodes(editor)
const elem2 = elem.nextSibling
......@@ -181,7 +137,7 @@ const ImageModal = (props, ref) => {
clear()
}
const onOnlineImageChange = (url) => {
const onOnlineImageChange = url => {
setImgUrl(url)
form.setFieldsValue({ imgUrl: url })
}
......@@ -195,7 +151,7 @@ const ImageModal = (props, ref) => {
<OnlineImageList imgUrl={imgUrl} onChange={onOnlineImageChange}></OnlineImageList>
</Form.Item>
) : (
<Form.Item label="上传图片" valuePropName="fileList" name="imgUrl" getValueFromEvent={normFile} rules={[{ required: true, message: '请上传图片' }]}>
<Form.Item label="上传图片" name="imgUrl" rules={[{ required: true, message: '请上传图片' }]}>
<Spin spinning={uploading} tip={`${progress}%`}>
<div className="editor-dragger">
<Dragger {...uploadProps} showUploadList={false}>
......@@ -209,18 +165,16 @@ const ImageModal = (props, ref) => {
</div>
)}
{imgUrl && (
<>
<div className="editor-uploader-result">
<div className="editor-uploader-result-img">
<img src={imgUrl} alt="" />
</div>
<div className="editor-uploader-result-tips">
<Button size="small" type="primary" ghost onClick={() => setImgUrl(null)}>
替换
</Button>
</div>
<div className="editor-uploader-result">
<div className="editor-uploader-result-img">
<img src={imgUrl} alt="" />
</div>
</>
<div className="editor-uploader-result-tips">
<Button size="small" type="primary" ghost onClick={() => setImgUrl(null)}>
替换
</Button>
</div>
</div>
)}
</Dragger>
</div>
......
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react'
import { Modal, Divider, Upload, Input, Space, Button, Form, Spin, message, Select, Cascader, ColorPicker, Row, Col } from 'antd'
import { SlateTransforms, SlateEditor, DomEditor, SlateElement } from '@wangeditor/editor'
import { useState, useEffect, forwardRef } from 'react'
import { Divider, Input, Space, Button, Form, message, Select, Cascader, ColorPicker, Row, Col } from 'antd'
import { SlateTransforms, SlateEditor, SlateElement } from '@wangeditor/editor'
import './index.less'
import { addChapterTooltip, delChapterTooltip } from '../utils/request'
import { fontSizeList } from '../utils/setting'
import { findTreeElementByKey } from '@/utils/common'
const LinkModal = forwardRef((props, ref) => {
const { editor, ossClient, bookId, chapterId, setLinkVisible, setLinkInfo, linkInfo, gData, selectionSize = 18 } = props
const LinkModal = (props, ref) => {
const { editor, setLinkVisible, setLinkInfo, linkInfo, gData, selectionSize = 18 } = props
const [form] = Form.useForm()
const linktype = Form.useWatch('linktype', form)
......@@ -20,9 +19,7 @@ const LinkModal = forwardRef((props, ref) => {
theme: '#ab1941',
fontSize: selectionSize || 18
})
const [toolStatus, setToolStatus] = useState(false)
const [nowRandom, setNowRandom] = useState(null)
const [fontsize, setFontsize] = useState(selectionSize)
const linkChange = value => {
if (value === 2) {
......@@ -75,7 +72,7 @@ const LinkModal = forwardRef((props, ref) => {
}
setLoading(true)
const { linktype, link, ...other } = values
const { link } = values
let newLink = ''
if (link) {
if (!/^https*:\/\//.test(link)) {
......@@ -143,47 +140,6 @@ const LinkModal = forwardRef((props, ref) => {
setLoading(false)
}
const deleteNowTooltip = async () => {
const data = await delChapterTooltip({
book_id: bookId,
chapter_id: chapterId,
position: nowRandom
})
if (data) {
editor.restoreSelection()
const nodeEntries = SlateEditor.nodes(editor, {
match: node => {
// JS syntax
if (SlateElement.isElement(node)) {
if (node.type === 'chapterLink') {
return true // 匹配 chapterToolTip
}
}
return false
},
universal: true
})
// 遍历匹配的节点迭代器,获取匹配的节点路径
let nodePaths = []
let nodes = []
if (nodeEntries === null) {
console.log('当前未选中的 chapterLink')
} else {
for (let nodeEntry of nodeEntries) {
const [node, path] = nodeEntry
nodePaths.push(path)
nodes.push(node)
}
// 将属性应用到匹配的节点
for (const path of nodePaths) {
SlateTransforms.removeNodes(editor, { at: path })
}
}
setNowRandom(null)
setLinkVisible(false)
}
}
return (
<div>
<Divider />
......@@ -256,11 +212,6 @@ const LinkModal = forwardRef((props, ref) => {
</Form.Item>
<Form.Item className="editor-form-buttons">
<Space>
{toolStatus && (
<Button type="default" onClick={deleteNowTooltip}>
删除
</Button>
)}
<Button type="primary" loading={loading} htmlType="submit">
{nowRandom ? '更新' : '插入'}
</Button>
......@@ -270,6 +221,6 @@ const LinkModal = forwardRef((props, ref) => {
</div>
</div>
)
})
}
export default LinkModal
export default forwardRef(LinkModal)
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react';
import {
Modal,
Divider,
Upload,
Input,
Space,
Button,
Form,
Spin,
message,
ColorPicker,
} from 'antd';
import { CloudUploadOutlined } from '@ant-design/icons';
import { useState, forwardRef, useImperativeHandle } from 'react'
import { Divider, Input, Space, Button, Form, ColorPicker } from 'antd'
import { SlateTransforms, SlateEditor, DomEditor, SlateElement } from '@wangeditor/editor';
import { SlateTransforms, SlateEditor, SlateElement } from '@wangeditor/editor'
import { setPracticeRandom } from '@/store/modules/editor';
import { useDispatch } from 'react-redux';
import './index.less';
import { setPracticeRandom } from '@/store/modules/editor'
import { useDispatch } from 'react-redux'
import './index.less'
const PracticeModal = forwardRef((props, ref) => {
const { bookId, chapterId, setPracticeOpenVisible } = props;
const dispatch = useDispatch();
const { editor, ossClient } = props;
const [form] = Form.useForm();
const [themeValue, setThemeValue] = useState('#ab1941');
const [initValues, setInitValues] = useState({ practice: '', theme: '#ab1941' });
const [nodes, setNodes] = useState(null);
const PracticeModal = (props, ref) => {
const { bookId, chapterId, setPracticeOpenVisible } = props
const dispatch = useDispatch()
const { editor } = props
const [form] = Form.useForm()
const [themeValue, setThemeValue] = useState('#ab1941')
const [initValues, setInitValues] = useState({ practice: '', theme: '#ab1941' })
const [nodes, setNodes] = useState(null)
useImperativeHandle(ref, () => {
return {
nodes,
};
});
nodes
}
})
const textColorChange = (value, hex) => {
setThemeValue(hex);
form.setFieldsValue({ theme: hex });
};
setThemeValue(hex)
form.setFieldsValue({ theme: hex })
}
const callback = (practiceNum, practiceTitle) => {
const nodeEntries = SlateEditor.nodes(editor, {
match: (node) => {
match: node => {
// JS syntax
if (SlateElement.isElement(node)) {
if (node.type === 'chapterPractice') {
return true;
return true
}
}
return false;
return false
},
universal: true,
});
universal: true
})
setNodes(nodeEntries);
dispatch(setPracticeRandom({ practiceNum, practiceTitle }));
};
setNodes(nodeEntries)
dispatch(setPracticeRandom({ practiceNum, practiceTitle }))
}
const onFinish = (values) => {
editor.restoreSelection();
const onFinish = values => {
editor.restoreSelection()
const nodeEntries = SlateEditor.nodes(editor, {
match: (node) => {
match: node => {
// JS syntax
if (SlateElement.isElement(node)) {
if (node.type === 'paragraph') {
return true; // 匹配 paragraph
return true // 匹配 paragraph
}
}
return false;
return false
},
universal: true,
});
universal: true
})
for (let nodeEntry of nodeEntries) {
const [node, path] = nodeEntry;
const [node] = nodeEntry
if (node.children[0].text === '') {
SlateTransforms.removeNodes(editor);
SlateTransforms.removeNodes(editor)
}
}
const practiceNum = Math.random().toString(32).substring(2, 10);
const practiceNum = Math.random().toString(32).substring(2, 10)
editor.insertNode({
type: 'chapterPractice',
title: values.practice,
......@@ -88,62 +76,44 @@ const PracticeModal = forwardRef((props, ref) => {
chapterId,
theme: values.theme,
callback: callback,
children: [{ text: '' }],
});
form.resetFields();
setPracticeOpenVisible(false);
editor.focus();
};
children: [{ text: '' }]
})
form.resetFields()
setPracticeOpenVisible(false)
editor.focus()
}
return (
<div>
<Divider />
<div className='editor-content-form'>
<Form
layout='vertical'
name='validate_other'
form={form}
onFinish={onFinish}
initialValues={initValues}
>
<Form.Item
label='标题'
name='practice'
rules={[{ required: true, message: '请输入标题' }]}
extra='最多输入100字'
>
<Input maxLength={100} placeholder='' allowClear />
<div className="editor-content-form">
<Form layout="vertical" name="validate_other" form={form} onFinish={onFinish} initialValues={initValues}>
<Form.Item label="标题" name="practice" rules={[{ required: true, message: '请输入标题' }]} extra="最多输入100字">
<Input maxLength={100} placeholder="" allowClear />
</Form.Item>
<Form.Item>
<div className='justcontent-color-inline'>
<div className="justcontent-color-inline">
<Form.Item
label='练习主题色'
name='theme'
className='flex-max'
label="练习主题色"
name="theme"
className="flex-max"
rules={[
{ required: true, message: '请选择颜色' },
{ pattern: /^#[0-9A-Fa-f]{6}$/i, message: '请输入正确的16进制色值' },
]}
>
<Input placeholder='' allowClear />
{ pattern: /^#[0-9A-Fa-f]{6}$/i, message: '请输入正确的16进制色值' }
]}>
<Input placeholder="" allowClear />
</Form.Item>
<Form.Item label={` `}>
<ColorPicker
disabledAlpha
value={themeValue}
defaultValue={themeValue}
format='hex'
onChange={textColorChange}
/>
<ColorPicker disabledAlpha value={themeValue} defaultValue={themeValue} format="hex" onChange={textColorChange} />
</Form.Item>
</div>
</Form.Item>
<Form.Item className='editor-form-buttons'>
<Form.Item className="editor-form-buttons">
<Space>
<Button type='default' onClick={() => setPracticeOpenVisible(false)}>
<Button type="default" onClick={() => setPracticeOpenVisible(false)}>
取消
</Button>
<Button type='primary' htmlType='submit'>
<Button type="primary" htmlType="submit">
插入
</Button>
</Space>
......@@ -151,7 +121,7 @@ const PracticeModal = forwardRef((props, ref) => {
</Form>
</div>
</div>
);
});
)
}
export default PracticeModal;
export default forwardRef(PracticeModal)
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react'
import { Modal, Divider, Upload, Input, Space, Button, Form, Spin, message, Select, ColorPicker, Row, Col } from 'antd'
import { SlateTransforms, SlateEditor, DomEditor, SlateElement } from '@wangeditor/editor'
import { useState, useEffect, forwardRef } from 'react'
import { Divider, Input, Space, Button, Form, message, Select, ColorPicker, Row, Col } from 'antd'
import { SlateTransforms, SlateEditor, SlateElement } from '@wangeditor/editor'
import './index.less'
import { addChapterTooltip, delChapterTooltip } from '../utils/request'
import { findNodeWithParent, fontSizeList } from '../utils/setting'
const TooltipModal = forwardRef((props, ref) => {
const { editor, ossClient, bookId, chapterId, setTooltipVisible, setTooltipInfo, tooltipInfo, selectionSize = 18 } = props
const TooltipModal = (props, ref) => {
const { editor, bookId, chapterId, setTooltipVisible, setTooltipInfo, tooltipInfo, selectionSize = 18 } = props
const [form] = Form.useForm()
const tooltipTypeValue = Form.useWatch('tooltipType', form)
......@@ -44,7 +44,7 @@ const TooltipModal = forwardRef((props, ref) => {
const onFinish = async values => {
editor.restoreSelection()
setLoading(true)
const { tooltipType, link, theme, fontSize, ...other } = values
const { tooltipType, link, theme, ...other } = values
let newLink = ''
if (link) {
if (!/^https*:\/\//.test(link)) {
......@@ -78,7 +78,6 @@ const TooltipModal = forwardRef((props, ref) => {
return
}
const text = editor.getSelectionText()
let random = Math.random().toString(10).substring(2, 10)
const data = await addChapterTooltip({
book_id: bookId,
......@@ -231,6 +230,6 @@ const TooltipModal = forwardRef((props, ref) => {
</div>
</div>
)
})
}
export default TooltipModal
export default forwardRef(TooltipModal)
import { useState, useEffect, useRef, forwardRef, useImperativeHandle } from 'react'
import { Button, Divider, Space, Modal } from 'antd'
import { EyeOutlined, SaveOutlined, CloseOutlined, HistoryOutlined } from '@ant-design/icons'
import AliOSS from 'ali-oss'
import dayjs from 'dayjs'
import './utils/iconfont'
......@@ -80,9 +79,7 @@ import PreviewModal from './components/preview'
import HistoryModal from './history/'
import $ from 'jquery'
import { getAliOSSSTSToken } from './utils/request'
import './index.less'
const bookBucketName = 'zxts-book-file'
const module = {
menus: [
......@@ -152,9 +149,6 @@ const WangEditorCustomer = (props, ref) => {
const toolbarRef = useRef()
const [ossClient, setOssClient] = useState(null) // oss 操作
const [STSToken, setSTSToken] = useState(null) // oss 过期设置
const [tabKey, setTabKey] = useState('text')
// editor 实例
const [editor, setEditor] = useState(null)
......@@ -615,71 +609,6 @@ const WangEditorCustomer = (props, ref) => {
setHistoryVisible(true)
}
const getStsAuthToken = async () => {
const data = await getAliOSSSTSToken()
if (data) {
window.sessionStorage.setItem('sts', JSON.stringify(data))
setSTSToken(data)
const ossClientTemp = new AliOSS({
accessKeyId: data.AccessKeyId,
accessKeySecret: data.AccessKeySecret,
stsToken: data.SecurityToken,
endpoint: 'zijingebook.com',
// region: 'cn-beijing',
// endpoint: data.endpoint,
bucket: bookBucketName,
timeout: 60000,
refreshSTSToken: async () => {
const info = await getAliOSSSTSToken()
return {
AccessKeyId: info.AccessKeyId,
AccessKeySecret: info.AccessKeySecret,
SecurityToken: info.SecurityToken
}
},
refreshSTSTokenInterval: 14 * 60 * 1000
})
setOssClient(ossClientTemp)
}
}
useEffect(() => {
;(async () => {
const tempStsToken = window.sessionStorage ? window.sessionStorage.getItem('sts') : ''
try {
const stsToken = JSON.parse(tempStsToken)
// 15 分钟过期
if (dayjs(stsToken.Expiration).valueOf() - dayjs().valueOf() >= 14 * 60 * 1000) {
getStsAuthToken()
} else {
const ossClientTemp = await new AliOSS({
accessKeyId: data.AccessKeyId,
accessKeySecret: data.AccessKeySecret,
stsToken: data.SecurityToken,
// endpoint: data.endpoint,
// region: 'cn-beijing',
endpoint: 'zijingebook.com',
bucket: bookBucketName,
timeout: 180000,
refreshSTSToken: async () => {
const info = await getAliOSSSTSToken()
return {
AccessKeyId: info.AccessKeyId,
AccessKeySecret: info.AccessKeySecret,
SecurityToken: info.SecurityToken
}
},
refreshSTSTokenInterval: 14 * 60 * 1000
})
setOssClient(ossClientTemp)
setSTSToken(stsToken)
}
} catch (e) {
getStsAuthToken()
}
})()
}, [])
const colorList = [
{ color: '#ab1941', name: '默认' },
{ color: '#2970f6', name: '蓝色' },
......@@ -799,18 +728,9 @@ const WangEditorCustomer = (props, ref) => {
}}
maskClosable={false}
onCancel={() => setImageVisible(false)}>
<ImageModal
ref={imageRef}
isOnline={isOnline}
editor={editor}
ossClient={ossClient}
STSToken={STSToken}
setImageVisible={setImageVisible}
imageInfo={imageInfo}
setImageInfo={setImageInfo}
/>
<ImageModal ref={imageRef} isOnline={isOnline} editor={editor} setImageVisible={setImageVisible} imageInfo={imageInfo} setImageInfo={setImageInfo} />
</Modal>
<VideoModal ref={videoRef} editor={editor} ossClient={ossClient} STSToken={STSToken} />
<VideoModal ref={videoRef} editor={editor} />
<Modal
open={galleryVisible}
footer={null}
......@@ -829,8 +749,6 @@ const WangEditorCustomer = (props, ref) => {
ref={galleryRef}
isOnline={isOnline}
editor={editor}
ossClient={ossClient}
STSToken={STSToken}
chapterId={chapterId}
bookId={bookId}
setGalleryVisible={setGalleryVisible}
......@@ -839,7 +757,7 @@ const WangEditorCustomer = (props, ref) => {
selectionSize={selectionSize}
/>
</Modal>
<AudioModal ref={audioRef} editor={editor} ossClient={ossClient} STSToken={STSToken} />
<AudioModal ref={audioRef} editor={editor} />
<Modal
open={titleVisible}
footer={null}
......@@ -853,15 +771,7 @@ const WangEditorCustomer = (props, ref) => {
}}
maskClosable={false}
onCancel={() => setTitleVisible(false)}>
<ChapterTitleModal
ref={chapterTitleRef}
editor={editor}
ossClient={ossClient}
STSToken={STSToken}
setTitleVisible={setTitleVisible}
titleInfo={titleInfo}
setTitleInfo={setTitleInfo}
/>
<ChapterTitleModal ref={chapterTitleRef} editor={editor} setTitleVisible={setTitleVisible} titleInfo={titleInfo} setTitleInfo={setTitleInfo} />
</Modal>
<Modal
......@@ -880,8 +790,6 @@ const WangEditorCustomer = (props, ref) => {
<ChapterItemModal
ref={chapterItemRef}
editor={editor}
ossClient={ossClient}
STSToken={STSToken}
setSectionVisible={setSectionVisible}
sectionInfo={sectionInfo}
setSectionInfo={setSectionInfo}
......@@ -902,18 +810,10 @@ const WangEditorCustomer = (props, ref) => {
}}
maskClosable={false}
onCancel={() => setPracticeOpenVisible(false)}>
<PracticeModal
ref={practiceRef}
chapterId={chapterId}
bookId={bookId}
editor={editor}
ossClient={ossClient}
STSToken={STSToken}
setPracticeOpenVisible={setPracticeOpenVisible}
/>
<PracticeModal ref={practiceRef} chapterId={chapterId} bookId={bookId} editor={editor} setPracticeOpenVisible={setPracticeOpenVisible} />
</Modal>
<FormulaModal ref={formulaRef} editor={editor} ossClient={ossClient} STSToken={STSToken} />
<FormulaModal ref={formulaRef} editor={editor} />
<Modal
open={tooltipVisible}
footer={null}
......@@ -932,8 +832,6 @@ const WangEditorCustomer = (props, ref) => {
editor={editor}
chapterId={chapterId}
bookId={bookId}
ossClient={ossClient}
STSToken={STSToken}
tooltipInfo={tooltipInfo}
setTooltipInfo={setTooltipInfo}
setTooltipVisible={setTooltipVisible}
......@@ -958,8 +856,6 @@ const WangEditorCustomer = (props, ref) => {
editor={editor}
chapterId={chapterId}
bookId={bookId}
ossClient={ossClient}
STSToken={STSToken}
gData={gData}
linkInfo={linkInfo}
setLinkInfo={setLinkInfo}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论