diff --git a/config/router.config.ts b/config/router.config.ts index 6c0be07..be65055 100644 --- a/config/router.config.ts +++ b/config/router.config.ts @@ -37,6 +37,11 @@ export default [ path: '/Calendar', component: './MainPage/ProjectManager/components/CalendarForm', }, + //富文本组件 + { + path: '/editor', + component: './MainPage/ProjectManager/components/WangEditor', + }, //401错误页 { exact: true, diff --git a/src/components/richText/wang/index.tsx b/src/components/richText/wang/index.tsx index e1151f8..e0efd6c 100644 --- a/src/components/richText/wang/index.tsx +++ b/src/components/richText/wang/index.tsx @@ -1,7 +1,10 @@ -import React, { useEffect, useImperativeHandle, useState } from 'react'; +import React, { useEffect, useImperativeHandle, useRef, useState } from 'react'; import AlertMenu from './fullScreen' import E from 'wangeditor'; -import { Button } from 'antd'; +import { Button, message, Spin } from 'antd'; +import { pictureDisplayPath, uploadAttachmentPath } from '@/utils/DownloadUtils'; +import { isEmpty } from '@/utils/CommonUtils'; +import { createNewFileBid } from '@/services/download_'; interface WangType { braftRef: any;//挂载 @@ -9,7 +12,9 @@ interface WangType { echo?: any;//回显内容 value?: any; height?: number; - onChange?: (value: any) => void + onChange?: (value: any) => void; + useImage?: boolean;//使用图片上传 + imageId?: string;//图片objectId } let editor: any = null; @@ -21,6 +26,10 @@ const BraftText: React.FC = (props) => { //======================================================================================state const [content, setContent] = useState(''); const [fullScreen, fullScreenSet] = useState(false); + //遮罩 + const [loading, setLoading] = useState(false); + //imageId + const objectId = useRef(null); const { braftRef, echo, @@ -28,12 +37,14 @@ const BraftText: React.FC = (props) => { value, height, onChange, + useImage, + imageId, } = props; const tools = [//工具栏 'head',//标题 'fontSize', //字号 - 'lineHeight', //行高 + // 'lineHeight', //行高 'foreColor', //颜色 'bold', //加粗 'italic', //斜体 @@ -41,12 +52,13 @@ const BraftText: React.FC = (props) => { 'strikeThrough', //文字删除线 'indent', //缩进 'justify', //文字对齐方式 + 'list', //列表 'undo', //撤销 - 'redo', //重做 + 'redo', //恢复 'fullscreen', //全屏 - // 'emoticon',//表情 // 'image',//图片 + // 'emoticon',//表情 // 'video',//视频 // 'table',//表格 // 'todo',//待办 @@ -56,12 +68,14 @@ const BraftText: React.FC = (props) => { useEffect(() => { if (willCreate) { // 注:class写法需要在componentDidMount 创建编辑器 - editor = new E("#div1") + editor = new E("#div1"); + //添加图片上传 + useImage && tools.splice(-3, 0, 'image'); //工具栏 editor.config.menus = tools; //提示 - editor.config.placeholder = '为了能顺利发布,建议您内容去掉下划线等格式,尽量以纯文本形式发布。' + editor.config.placeholder = '为了能顺利发布,建议您内容去掉下划线等格式,尽量以纯文本形式发布。'; // 配置 onchange 回调函数 editor.config.onchange = editorOnChange; // 注册菜单 @@ -73,6 +87,104 @@ const BraftText: React.FC = (props) => { // 设置编辑区域高度为 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(); @@ -99,6 +211,7 @@ const BraftText: React.FC = (props) => { getHtml, getHtml1, makeDis, + getImageId, })); // 获取html方法1 @@ -131,12 +244,17 @@ const BraftText: React.FC = (props) => { const triggerChange = (newHtml: any) => { onChange?.(newHtml); }; + + //获取富文本图片objectId + function getImageId() { + return objectId.current; + } return ( -
- {/* - */} -
-
+ +
+
+
+
) } export default BraftText \ No newline at end of file diff --git a/src/pages/MainPage/ProjectManager/components/WangEditor.tsx b/src/pages/MainPage/ProjectManager/components/WangEditor.tsx new file mode 100644 index 0000000..025fa87 --- /dev/null +++ b/src/pages/MainPage/ProjectManager/components/WangEditor.tsx @@ -0,0 +1,41 @@ +import React, { useRef, useState } from 'react'; +import { Button, Typography } from 'antd'; +import BraftText from '@/components/richText/wang'; +import ProCard from '@ant-design/pro-card'; +import { isEmpty } from '@/utils/CommonUtils'; + +const Editor: React.FC<{}> = () => { + const braftRef = useRef(null); + const [text, setText] = useState(); + const [code, setCode] = useState(); + const { Text, Paragraph } = Typography; + return ( + + + setText(value)} useImage /> + + + {code} + + + }> + {isEmpty(text) ? '没有' : ( + +
+                            
+                                {text}
+                            
+                        
+
+ )} +
+
+ ); +}; + +export default Editor;