frontend-template/src/components/Editor/index.tsx

134 lines
3.5 KiB
TypeScript

import React, { useEffect, useState } from 'react';
import BraftEditor, { EditorState, ExtendControlType, MediaType } from 'braft-editor';
import classnames from 'classnames';
import EditorPreview from './EditorPreview';
import 'braft-editor/dist/index.css';
export interface IEditorProps {
/**
* 富文本html代码段
*/
value: string;
/**
* 请求实例
*/
request?: any;
/**
* 上传接口
*/
action?: string;
/**
* 上传中除了 order 外的额外参数
*/
data?: {
[propName: string]: any;
};
/**
* 组件样式类名称前缀
*/
prefixCls?: string;
/**
* 容器节点样式类名称
*/
className?: string;
/**
* 容器节点样式
*/
style?: React.CSSProperties;
[propName: string]: any;
}
// 上传到服务端的排序号
let order = 0;
const Editor: React.FC<IEditorProps> = (props) => {
const { value, request, action, data, prefixCls, className, style, onChange, ...rest } = props;
// 富文本数据是否初始化
const [isInit, setIsInit] = useState(false);
// 富文本
const [editorState, setEditorState] = useState<EditorState>(BraftEditor.createEditorState(value));
// 富文本预览
const [previewVisible, setPreviewVisible] = useState<boolean>(false);
// onChange
const handleEditorChange = (newEditorState: EditorState) => {
if (isInit || (!isInit && value === '<p></p>')) {
setIsInit(true);
setEditorState(newEditorState);
const changeValue = newEditorState.toHTML() === '<p></p>' ? '' : newEditorState.toHTML();
onChange(changeValue);
}
};
// 富文本预览
const extendControls: ExtendControlType[] = [
{
key: 'preview-button',
type: 'button',
text: '预览',
onClick: () => setPreviewVisible(true),
},
];
// 自定义媒体
const media: MediaType = {
uploadFn: async ({ file, progress, error, success }) => {
// 自定义上传
const baseRequestForm = request.requestForm.bind(request);
order += 1;
baseRequestForm(
action,
{ file, order, ...data },
{
onUploadProgress: ({ total, loaded }: { total: number; loaded: number }) => {
progress((loaded / total) * 100);
},
},
)
.then((res: any) => {
const newRes = res.value || res.valueObj || {};
const { imageUrl = '', attachUrl = '', attachId = '' } = newRes;
res.url = imageUrl || attachUrl;
res.uid = attachId;
res.width = '100%';
res.height = 'auto';
success(res);
})
.catch(error);
},
};
useEffect(() => {
if (!isInit && value !== '<p></p>') {
setEditorState(BraftEditor.createEditorState(value));
setIsInit(true);
}
}, [value]);
return (
<div>
<BraftEditor
className={classnames(className, `${prefixCls}-wrapper`)}
style={style}
contentStyle={{ boxShadow: 'inset 0 1px 3px rgba(0,0,0,.1)' }}
contentClassName="editor-content"
extendControls={extendControls}
// media={media}
value={editorState}
onChange={handleEditorChange}
textBackgroundColor={false}
stripPastedStyles
{...rest}
/>
<EditorPreview
width={600}
value={editorState.toHTML()}
visible={previewVisible}
onCancel={() => setPreviewVisible(false)}
/>
</div>
);
};
Editor.defaultProps = {
value: '<p></p>',
data: {},
className: '',
style: {},
};
export default Editor;