Files
fe_service_ebtp_frontend/src/components/richText/wang/index.tsx
2022-07-15 16:36:06 +08:00

263 lines
8.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useEffect, useImperativeHandle, useRef, useState } from 'react';
import AlertMenu from './fullScreen'
import E from 'wangeditor';
import { Button, message, Spin } from 'antd';
import { pictureDisplayPath, uploadAttachmentPath } from '@/utils/DownloadUtils';
import { isEmpty, isNotEmpty } from '@/utils/CommonUtils';
import { createNewFileBid } from '@/services/download_';
interface WangType {
braftRef: any;//挂载
disabled?: any;//是否可编辑
echo?: any;//回显内容
value?: any;
height?: number;
onChange?: (value: any) => void;
useImage?: boolean;//使用图片上传
imageId?: string;//图片objectId
}
let editor: any = null;
const BraftText: React.FC<WangType> = (props) => {
let willCreate = true;
// 菜单 key ,各个菜单不能重复-自定义工具
const menuKey = 'alertMenuKey'
//======================================================================================state
const [content, setContent] = useState('');
const [fullScreen, fullScreenSet] = useState(false);
//遮罩
const [loading, setLoading] = useState(false);
//imageId
const objectId = useRef<string | null | undefined>(null);
const {
braftRef,
echo,
disabled,
value,
height,
onChange,
useImage,
imageId,
} = props;
const tools = [//工具栏
'head',//标题
'fontSize', //字号
// 'lineHeight', //行高
'foreColor', //颜色
'bold', //加粗
'italic', //斜体
'underline', //下划线
'strikeThrough', //文字删除线
'indent', //缩进
'justify', //文字对齐方式
'list', //列表
'undo', //撤销
'redo', //恢复
'fullscreen', //全屏
// 'image',//图片
// 'emoticon',//表情
// 'video',//视频
// 'table',//表格
// 'todo',//待办
];
//=======================================================================================func
useEffect(() => {
if (willCreate) {
// 注class写法需要在componentDidMount 创建编辑器
editor = new E("#div1");
//添加图片上传
useImage && tools.splice(-3, 0, 'image');
//工具栏
editor.config.menus = tools;
//提示
editor.config.placeholder = '为了能顺利发布,建议您内容去掉下划线等格式,尽量以纯文本形式发布。';
// 配置 onchange 回调函数
editor.config.onchange = editorOnChange;
// 注册菜单
// editor.menus.extend(menuKey, AlertMenu);
// 将菜单加入到 editor.config.menus 中 const menuKey = 'alertMenuKey'
// 也可以通过配置 menus 调整菜单的顺序,参考【配置菜单】部分的文档 editor.config.menus.push(menuKey)
// editor.config.menus = editor.config.menus.concat(menuKey)
// 设置编辑区域高度为 500px
height && (editor.config.height = height);
//关闭网络上传图片
editor.config.showLinkImg = false;
// 关闭粘贴内容中的样式
editor.config.pasteFilterStyle = false;
// 忽略粘贴内容中的图片
editor.config.pasteIgnoreImg = true;
// 上传图片到服务器,对应的是controller层的@RequestMapping("/upload")
editor.config.uploadImgServer = uploadAttachmentPath;//接口名称
//自定义name,接收的时候图片文件的那么用这个对应的是参数中的MultipartFile upimg名称,这个名称即上传到浏览器的参数名称
editor.config.uploadFileName = "multipartFiles";//这个需要和后台商量上传图片的名称
//设置请求体额外参数
if (useImage) {
if (isEmpty(imageId)) {
createNewFileBid().then(res => {//获取雪花id
editor.config.uploadImgParams = {
appCode: 'ebtp-cloud-frontend',
objectId: res?.id,
};
objectId.current = res?.id;
})
} else {
editor.config.uploadImgParams = {
appCode: 'ebtp-cloud-frontend',
objectId: imageId,
};
objectId.current = imageId;
}
}
// 将 timeout 时间改为 60s
editor.config.uploadImgTimeout = 60000;
// 将图片大小限制为 600k
editor.config.uploadImgMaxSize = 600 * 1024;
// 限制一次最多上传 1 张图片
editor.config.uploadImgMaxLength = 1;
//上传图片的错误提示默认使用alert弹出,也可以自定义用户体验更好的提示方式
editor.config.customAlert = function (info: string) {
const repinfo = info.replace(/0.5859375M/g, '600K');
// info 是需要提示的内容
message.error(repinfo);
};
// 上传图片的结果反馈
editor.config.uploadImgHooks = {
before: function (xhr: any, editor: any, files: any) {
// 图片上传之前触发
// xhr 是 XMLHttpRequst 对象editor 是编辑器对象files 是选择的图片文件
// 如果返回的结果是 {prevent: true, msg: 'xxxx'} 则表示用户放弃上传
// return {
// prevent: true,
// msg: '放弃上传'
// }
// console.log("before:",xhr)
if (isEmpty(objectId.current)) {
return {
prevent: true,
msg: '上传失败,原因:上传参数错误'
}
}
setLoading(true);
return {
prevent: false,
}
},
success: function (xhr: any, editor: any, result: any) {
// 图片上传并返回结果,图片插入成功之后触发
// xhr 是 XMLHttpRequst 对象editor 是编辑器对象result 是服务器端返回的结果
// console.log("success:",result)
},
fail: function (xhr: any, editor: any, result: any) {
// 图片上传并返回结果,但图片插入错误时触发
// xhr 是 XMLHttpRequst 对象editor 是编辑器对象result 是服务器端返回的结果
},
error: function (xhr: any, editor: any) {
// 图片上传出错时触发
// xhr 是 XMLHttpRequst 对象editor 是编辑器对象
},
// 上传图片超时
timeout: function (xhr: any) {
message.error('服务器超时!');
setLoading(false);
},
// 如果服务器端返回的不是 {errno:0, data: [...]} 这种格式,可使用该配置
// (但是,服务器端返回的必须是一个 JSON 格式字符串!!!否则会报错)
customInsert: function (insertImg: (arg0: any) => void, result: any, editor: any) {
// 图片上传并返回结果,自定义插入图片的事件(而不是编辑器自动插入图片!!!)
// insertImg 是插入图片的函数参数editor 是编辑器对象result 是服务器端返回的结果
// 举例:假如上传图片成功后,服务器端返回的是 {url:'....'} 这种格式,即可这样插入图片:
if (result?.success) {
const url = pictureDisplayPath + '?filePath=' + result.data[0].sysStorageVO.filePath;
insertImg(url);
} else {
message.error('图片上传失败!');
}
setLoading(false);
// var url = result.result.remote_path;
// insertImg(url);
// result 必须是一个 JSON 格式字符串!!!否则报错
}
};
/**一定要创建 */
editor.create();
//控制是否可编辑
disabled && makeDis();
willCreate = false;
}
return () => {
// 组件销毁时销毁编辑器 注class写法需要在componentWillUnmount中调用
editor.destroy()
setLoading(false);
setContent('');
}
}, []);
useEffect(() => {
// 重新设置编辑器内容
echo && editor.txt.html(echo);
}, [echo])
/**
*提供给父级的内容
**/
useImperativeHandle(braftRef, () => ({
getText,
getHtml,
getHtml1,
makeDis,
getImageId,
}));
// 获取html方法1
function getHtml() {
return content
}
// 获取html方法2
function getHtml1() {
return editor.txt.html()
}
// 获取text
function getText() {
alert(editor.txt.text())
}
//change
function editorOnChange(newHtml: any) {
setContent(newHtml);
triggerChange(newHtml)
}
//不可编辑
function makeDis() {
editor.disable();
}
//form取值
const triggerChange = (newHtml: any) => {
onChange?.(newHtml);
};
//获取富文本图片objectId
function getImageId() {
return objectId.current;
}
return (
<Spin spinning={loading} tip={"上传中……"}>
<div>
<div id="div1" style={{ textAlign: 'left' }}></div>
</div>
</Spin>
)
}
export default BraftText