diff --git a/package.json b/package.json
index 49b7d76..aeed66a 100644
--- a/package.json
+++ b/package.json
@@ -43,7 +43,6 @@
"@ant-design/pro-table": "^2.54.3",
"@umijs/route-utils": "^1.0.36",
"antd": "^4.16.13",
- "braft-editor": "^2.3.9",
"classnames": "^2.2.6",
"crypto-js": "^4.0.0",
"lodash": "^4.17.11",
@@ -56,7 +55,8 @@
"react-dom": "^17.0.0",
"react-helmet-async": "^1.0.4",
"react-transition-group": "^4.4.2",
- "umi": "^v3.4.0"
+ "umi": "^v3.4.0",
+ "wangeditor": "^4.7.8"
},
"devDependencies": {
"@ant-design/pro-cli": "^2.0.2",
diff --git a/src/components/Editor/BraftEditor.tsx b/src/components/Editor/BraftEditor.tsx
deleted file mode 100644
index bdefef6..0000000
--- a/src/components/Editor/BraftEditor.tsx
+++ /dev/null
@@ -1,157 +0,0 @@
-/* eslint-disable */
-
-import type { EditorProps } from '.';
-import React, { useState, useEffect, useMemo } from 'react';
-// 引入编辑器组件
-import type { EditorState } from 'braft-editor';
-import { ContentUtils } from 'braft-utils';
-import BraftEditor from 'braft-editor';
-// 引入编辑器样式
-import 'braft-editor/dist/index.css';
-import { debounce } from 'lodash';
-import I18n from '@/utils/I18nUtils';
-import { Button, Modal, Spin, Tabs, Upload } from 'antd';
-import { ImageUtils } from 'braft-finder';
-import Icon from '../Icon';
-import type { UploadFile } from 'antd/lib/upload/interface';
-import { PlusOutlined } from '@ant-design/icons';
-import FileUtils from '@/utils/FileUtils';
-
-const defaultLanguage = 'zh';
-
-type languageType = 'zh' | 'zh-hant' | 'en' | 'tr' | 'ru' | 'jpn' | 'kr' | 'pl' | 'fr' | 'vi-vn';
-
-const languages: string[] = ['zh', 'zh-hant', 'en', 'tr', 'ru', 'jpn', 'kr', 'pl', 'fr', 'vi-vn'];
-
-const uploadButton = (
-
-);
-
-export default ({
- value,
- onChange,
- uploadImage,
- uploadVideo,
- uploadAudio,
- readOnly,
-}: EditorProps) => {
- const [es, setEs] = useState(BraftEditor.createEditorState(null));
- const [loading, setLoading] = useState(false);
- const [imageVisible, setImageVisible] = useState(false);
- const [imageList, setImageList] = useState([]);
-
- const debounceChange = useMemo(
- () =>
- debounce((nes: EditorState) => {
- setEs(nes);
- if (onChange) {
- onChange(nes.toHTML());
- }
- }, 500),
- [onChange],
- );
-
- const sl = I18n.getLocal().split('-')[0];
- const language = languages.indexOf(sl) === -1 ? defaultLanguage : sl;
-
- useEffect(() => {
- if (es.toHTML() !== value) {
- setEs(BraftEditor.createEditorState(value));
- }
- }, [value]);
-
- return (
- <>
-
- setImageVisible(true)}
- // >
- //
- //
- // ),
- // },
- ]
- }
- onChange={debounceChange}
- />
-
-
-
-
- 添加远程资源
-
-
-
-
- >
- }
- onCancel={() => setImageVisible(false)}
- >
- {imageList.length === 0 ? (
- {
- const is: UploadFile[] = [];
- fileList.forEach((file) => is.push({ ...file, status: 'done' }));
- setImageList(is);
- }}
- >
-
-
-
- 单击或拖动文件到此区域进行上传
- 支持单次或批量上传。
-
- ) : (
- setImageList(fileList)}
- >
- {uploadButton}
-
- )}
-
- >
- );
-};
diff --git a/src/components/Editor/WangEditor.tsx b/src/components/Editor/WangEditor.tsx
index 7f2f26e..2929065 100644
--- a/src/components/Editor/WangEditor.tsx
+++ b/src/components/Editor/WangEditor.tsx
@@ -1,41 +1,89 @@
-// import type { EditorProps } from '.';
-// import WangEditor from 'wangeditor';
-// import { useState, useEffect } from 'react';
-
-// const editorId = 'wang-editor-dom';
-// export default ({ value, onChange, uploadImage }: EditorProps) => {
-// const [editor, setEditor] = useState();
-// const [content, setContent] = useState();
-
-// useEffect(() => {
-// const we = new WangEditor(`#${editorId}`);
-// setEditor(we);
-
-// we.config.onchange = (val: string) => {
-// if (onChange) {
-// onChange(val);
-// }
-// };
-
-// we.config.customUploadImg = (files, insertImg)=>{
-// }
-
-// we.create();
-
-// return () => {
-// we.destroy();
-// };
-// }, [onChange]);
-
-// useEffect(() => {
-// if (value !== editor?.txt.html()) {
-// editor?.txt.html(value);
-// }
-// }, [editor, value]);
-
-// return (
-// <>
-//
-// >
-// );
-// };
+import type { WangEditorProps } from '.';
+import WangEditor from 'wangeditor';
+import { useState, useEffect, useCallback } from 'react';
+import FileUtils from '@/utils/FileUtils';
+import UrlUtils from '@/utils/UrlUtils';
+
+export default ({
+ readOnly,
+ value,
+ onChange,
+ uploadImage,
+ uploadVideo,
+ uploadAudio,
+}: WangEditorProps) => {
+ const [editor, setEditor] = useState();
+
+ const update = useCallback(
+ (val: string) => {
+ if (onChange) {
+ onChange(val);
+ }
+ },
+ [onChange],
+ );
+
+ useEffect(() => {
+ const we = new WangEditor(`#wang-editor-dom`);
+ setEditor(we);
+ we.config.onchange = (val: string) => update(val);
+
+ // if(uploadImage){
+ we.config.customUploadImg = (files: File[], insertFn: (url: string) => void) => {
+ if (uploadImage) {
+ // 自定义上传
+ uploadImage(files).then((urls) => {
+ urls.forEach((url) => {
+ insertFn(UrlUtils.resolveImage(url));
+ });
+ });
+ } else {
+ // base64解析上传
+ files.forEach((file) => {
+ FileUtils.getBase64(file).then((b6) => {
+ insertFn(b6 as string);
+ });
+ });
+ }
+ };
+
+ if (uploadVideo) {
+ we.config.customUploadVideo = (files: File[], insertFn: (url: string) => void) => {
+ uploadVideo(files).then((urls) => {
+ urls.forEach((url) => {
+ insertFn(UrlUtils.resolveVideo(url));
+ });
+ });
+ };
+ }
+
+ // 用户无操作 200 毫秒更新值
+ we.config.onchangeTimeout = 200;
+ we.config.zIndex = 100;
+ we.create();
+
+ return () => {
+ we.destroy();
+ };
+ }, [uploadImage, uploadVideo, uploadAudio]);
+
+ useEffect(() => {
+ if (readOnly) {
+ editor?.disable();
+ } else {
+ editor?.enable();
+ }
+ }, [editor, readOnly]);
+
+ useEffect(() => {
+ if (value !== editor?.txt.html()) {
+ editor?.txt.html(value);
+ }
+ }, [editor, value]);
+
+ return (
+ <>
+
+ >
+ );
+};
diff --git a/src/components/Editor/index.ts b/src/components/Editor/index.ts
index dda7f7b..e7b2fe9 100644
--- a/src/components/Editor/index.ts
+++ b/src/components/Editor/index.ts
@@ -1,5 +1,5 @@
-import Editor from './BraftEditor';
+import WangEditor from './WangEditor';
export * from './typings';
-export default Editor;
+export default WangEditor;
diff --git a/src/components/Editor/typings.ts b/src/components/Editor/typings.ts
index 00000f6..898f00b 100644
--- a/src/components/Editor/typings.ts
+++ b/src/components/Editor/typings.ts
@@ -2,10 +2,14 @@ export type EditorProps = {
value?: string;
onChange?: (val: string) => void;
// 上传图片, 返回图片完整地址 例: http://www.baidu.com/1.jpg
- uploadImage?: (blob: Blob) => Promise;
+ uploadImage?: (blobs: Blob[]) => Promise;
// 上传视频, 返回视频完整地址 例: http://www.baidu.com/1.mp3, 未指定时不允许上传视频
- uploadVideo?: (blob: Blob) => Promise;
+ uploadVideo?: (blobs: Blob[]) => Promise;
// 上传音频, 返回音频完整地址 例: http://www.baidu.com/1.mp3, 未指定时不允许上传音频
- uploadAudio?: (blob: Blob) => Promise;
+ uploadAudio?: (blobs: Blob[]) => Promise;
readOnly?: boolean;
};
+
+export type WangEditorProps = {
+ // editorId?: string;
+} & EditorProps;
diff --git a/src/components/RightContent/AvatarDropdown.tsx b/src/components/RightContent/AvatarDropdown.tsx
index 40bfc9d..a4e5b8e 100644
--- a/src/components/RightContent/AvatarDropdown.tsx
+++ b/src/components/RightContent/AvatarDropdown.tsx
@@ -9,7 +9,7 @@ import styles from './index.less';
import { outLogin } from '@/services/ant-design-pro/api';
import { User, Token } from '@/utils/Ballcat';
import I18n from '@/utils/I18nUtils';
-import SrcUtils from '@/utils/SrcUtils';
+import UrlUtils from '@/utils/UrlUtils';
export type GlobalHeaderRightProps = {
exitConfirm?: boolean;
@@ -102,7 +102,7 @@ const AvatarDropdown: React.FC = ({ exitConfirm }) => {
{user?.info?.nickname}
diff --git a/src/pages/notify/announcement/AnnouncementPage.tsx b/src/pages/notify/announcement/AnnouncementPage.tsx
index 534e73e..c40e50c 100644
--- a/src/pages/notify/announcement/AnnouncementPage.tsx
+++ b/src/pages/notify/announcement/AnnouncementPage.tsx
@@ -269,18 +269,18 @@ export default () => {
rules={[{ required: true, message: '请输入公告标题!' }]}
/>
- {/* */}
-
-
+ {
+ return announcement.uploadImage(blobs).then(({ data }) => {
+ return data;
+ });
+ }}
+ />
{
size="large"
style={{ cursor: 'pointer' }}
icon={}
- src={SrcUtils.resolve(record.avatar)}
+ src={UrlUtils.resolveImage(record.avatar)}
/>
);
diff --git a/src/services/ballcat/notify/announcement/index.ts b/src/services/ballcat/notify/announcement/index.ts
index a17c709..a006bff 100644
--- a/src/services/ballcat/notify/announcement/index.ts
+++ b/src/services/ballcat/notify/announcement/index.ts
@@ -1,5 +1,4 @@
import type { PageResult, QueryParam, R } from '@/typings';
-import type { UploadFile } from 'antd/lib/upload/interface';
import { request } from 'umi';
import type { AnnouncementDto, AnnouncementQo, AnnouncementVo } from './typings';
@@ -31,35 +30,37 @@ export async function del(body: AnnouncementVo) {
}
export function publish(body: AnnouncementVo) {
- return request(`notify/announcement/publish/${body.id}`, {
- method: 'patch',
+ return request>(`notify/announcement/publish/${body.id}`, {
+ method: 'PATCH',
});
}
export function close(body: AnnouncementVo) {
- return request(`notify/announcement/close/${body.id}`, {
- method: 'patch',
+ return request>(`notify/announcement/close/${body.id}`, {
+ method: 'PATCH',
});
}
-export function uploadImage(resultFiles: UploadFile[]) {
- const formData = new FormData();
- resultFiles.forEach((file) => {
- formData.append('files', file.originFileObj as Blob);
+export function uploadImage(blobs: Blob[]) {
+ const fd = new FormData();
+ blobs.forEach((blob) => {
+ fd.append('files', blob);
});
- return request('notify/announcement/image', {
- body: formData,
+
+ return request>('notify/announcement/image', {
+ method: 'POST',
+ body: fd,
});
}
export function getUserAnnouncements() {
- return request('notify/announcement/user', {
- method: 'get',
+ return request>('notify/announcement/user', {
+ method: 'GET',
});
}
export function readAnnouncement(id: string) {
- return request(`notify/user-announcement/read/${id}`, {
- method: 'patch',
+ return request>(`notify/user-announcement/read/${id}`, {
+ method: 'PATCH',
});
}
diff --git a/src/utils/SrcUtils.ts b/src/utils/SrcUtils.ts
deleted file mode 100644
index 620cb6b..0000000
--- a/src/utils/SrcUtils.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-function resolve(url?: string) {
- if (url && !url.startsWith('http')) {
- return `https://hccake-img.oss-cn-shanghai.aliyuncs.com/${url}`;
- }
- return url;
-}
-
-export default { resolve };
diff --git a/src/utils/UrlUtils.ts b/src/utils/UrlUtils.ts
new file mode 100644
index 0000000..78bb8fc
--- /dev/null
+++ b/src/utils/UrlUtils.ts
@@ -0,0 +1,13 @@
+const resolveImage = (url: string) => {
+ if (url && !url.startsWith('http')) {
+ return `https://hccake-img.oss-cn-shanghai.aliyuncs.com/${url}`;
+ }
+ return url;
+};
+
+const resolveVideo = (url: string) => url;
+
+const resolveAudio = (url: string) => url;
+
+const UrlUtils = { resolveImage, resolveVideo, resolveAudio };
+export default UrlUtils;