使用wangEditor上传图片,默认的上传serve,一直成功但是返回数据错误,可能是接口携带的参数有问题,此代码未被注释部分是我项目用到的配置,无视频,里面所有配置基本都加上,注释较多,请耐心观看
import React, { useState, useEffect } from "react";
import "@wangeditor/editor/dist/css/style.css"; // 引入 cssß
import { Editor, Toolbar } from "@wangeditor/editor-for-react";
import type { IDomEditor, IEditorConfig, IToolbarConfig } from "@wangeditor/editor";
// import { DomEditor } from "@wangeditor/editor";
// import api from "@/api/messageCenter";
// import { message } from "antd";
// import { uchoiceToken, uliveToken } from "@/utils/auth";
import { getUliveAdminBaseUrl } from "@/utils/getBaseUrl";
import type { SlateElement } from "@wangeditor/editor";
export type ImageElement = SlateElement & {
src: string;
alt: string;
url: string;
href: string;
};
export type InsertFnType = (url: string, alt: string, href: string) => void;
function MyEditor(props: any) {
// editor 实例
const [editor, setEditor] = useState<IDomEditor | any>(null); // TS 语法
// 编辑器内容
const [html, setHtml] = useState("");
// 模拟 ajax 请求,异步设置 html
// useEffect(() => {
// setTimeout(() => {
// setHtml("<p>hello world</p>");
// }, 1500);
// }, []);
// 工具栏配置
const toolbarConfig: Partial<IToolbarConfig> = {
//去除的选项
excludeKeys: [
"headerSelect", //正文,标题
"blockquote", //引用
// "|",//隔符
"bold", //加粗
"underline", //下划线
"italic", //斜体
"group-more-style", //样式
"color", //颜色
"bgColor", //背景色
"fontSize", //字体大小
"fontFamily", //字体
// "lineHeight",行高
"bulletedList", //无序列表
"numberedList", //有序列表
"todo", //待办
"group-justify", //对齐
"group-indent", //缩进
// "emotion",//表情
"insertLink", //链接
// "group-image", //图片
"group-video", //视频
"insertTable", //插表格
"codeBlock", //代码块
"divider" //分割线
// "undo",//撤销
// "redo",//重做
// "fullScreen"//全屏
]
}; // TS 语法
// 自定义校验图片
function customCheckImageFn(src: string, alt: string, url: string): boolean | undefined | string {
// TS 语法
if (!src) {
return;
}
if (src.indexOf("http") !== 0) {
return "图片网址必须以 http/https 开头";
}
return true;
// 返回值有三种选择:
// 1. 返回 true ,说明检查通过,编辑器将正常插入图片
// 2. 返回一个字符串,说明检查未通过,编辑器会阻止插入。会 alert 出错误信息(即返回的字符串)
// 3. 返回 undefined(即没有任何返回),说明检查未通过,编辑器会阻止插入。但不会提示任何信息
}
// 转换图片链接
function customParseImageSrc(src: string): string {
// TS 语法
if (src.indexOf("http") !== 0) {
return `http://${src}`;
}
return src;
}
// 编辑器配置
const editorConfig: Partial<IEditorConfig> = {
// TS 语法
placeholder: "请输入内容...",
autoFocus: false,
// 粘贴
// customPaste: (editor: IDomEditor, event: ClipboardEvent): boolean => {
// //const html = event.clipboardData?.getData("text/html"); // 获取粘贴的 html
// const text = event.clipboardData?.getData("text/plain"); // 获取粘贴的纯文本
// // const rtf = event.clipboardData.getData('text/rtf') // 获取 rtf 数据(如从 word wsp 复制粘贴)
// editor.insertText(text ? text : "");
// event.preventDefault();
// return false;
// },
//插图
MENU_CONF: {
// 不一定要使用,插图配置
insertImage: {
onInsertedImage(imageNode: ImageElement | null) {
// TS 语法
if (imageNode == null) {
return;
}
const { src, alt, url, href } = imageNode;
console.log("inserted image", src, "|", alt, "|", url, "|", href);
},
checkImage: customCheckImageFn, // 也支持 async 函数
parseImageSrc: customParseImageSrc // 也支持 async 函数
},
//上传图片
uploadImage: {
// server: "/api-base/upload/uploadFile",
// form-data fieldName ,默认值 'wangeditor-uploaded-image'
// fieldName: "file-uploaded-image",
// 单个文件的最大体积限制,默认为 2M
maxFileSize: 4 * 1024 * 1024, // 4M
// 最多可上传几个文件,默认为 100
maxNumberOfFiles: 10,
// 选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 []
// allowedFileTypes: [],
// 自定义上传参数,例如传递验证的 token 等。参数会被添加到 formData 中,一起上传到服务端。
// meta: {
// token: uchoiceToken.get(),
// // otherKey: "yyy"
// // file: ""
// },
// 将 meta 拼接到 url 参数中,默认 false
// metaWithUrl: false,
// 自定义增加 http header
// headers: {
// // Accept: "image/x-json",
// // otherKey: "xxx",
// Authorization: "Bearer " + uchoiceToken.get(),
// // "Content-Type": "multipart/form-data"
// Content: {
// Type: "application/json"
// }
// },
// 跨域是否传递 cookie ,默认为 false
// withCredentials: true,
// 超时时间,默认为 10 秒
timeout: 5 * 1000, // 5 秒
//最大字数
// maxLength: 500
// 上传之前触发
// onBeforeUpload(file: File) {
// // file 选中的文件,格式如 { key: file }
// return file;
// // 可以 return
// // 1. return file 或者 new 一个 file ,接下来将上传
// // 2. return false ,不上传这个 file
// },
// 上传进度的回调函数
onProgress(progress: number) {
// progress 是 0-100 的数字
console.log("progress", progress);
},
// 单个文件上传成功之后
onSuccess(file: File, res: any) {
console.log(`${file.name} 上传成功`, res);
},
// 单个文件上传失败
onFailed(file: File, res: any) {
console.log("qz-失败url", getUliveAdminBaseUrl());
console.log(`${file.name} 上传失败`, res);
},
// 上传错误,或者触发 timeout 超时
onError(file: File, err: any, res: any) {
console.log("qz-失败", res);
console.log(`${file.name} 上传出错`, err, res);
},
// 自定义插入图片
// customInsert(res: any, insertFn: InsertFnType) { // TS 语法
// // res 即服务端的返回结果
// // const result = res;
// // console.log("qz", result);
// const { url, alt, href } = res;
// // 从 res 中找到 url alt href ,然后插图图片
// insertFn(url, alt, href);
// },
// customUpload(file: File, insertFn: InsertFnType) { // TS 语法
// // file 即选中的文件
// // 自己实现上传,并得到图片 url alt href
// // 最后插入图片
// console.log("qz---file", file);
// // const { url, alt, href } = file;
// // insertFn(url, alt, href);
// }
// 用户自定义上传图片
customUpload(file: any, insertFn: any) {
console.log("qz-上传地址", getUliveAdminBaseUrl());
const axios = require("axios");
const FormData = require("form-data");
const data = new FormData();
data.append("file", file); // file 即选中的文件 主要就是这个传的参数--查看接口需要带什么参数
const config = {
method: "post",
url: `${getUliveAdminBaseUrl()}api-base/upload/uploadFile`, //上传图片地址 建议使用模板字符串拼接
// headers: {
// "Content-Type": "multipart/form-data",
// Authorization: "Bearer " + uliveToken.get()
// },//
data: data
};
axios(config)
.then(function (res: any) {
console.log("qz-用户自定义上传图片", res);
// const url = "https:// /" + res.data.data.path; //拼接成可浏览的图片地址
insertFn(res.data.result); //插入图片
})
.catch(function (error: any) {
console.log(error);
});
}
}
}
};
useEffect(() => {
// console.log("qz-props.htmlContent", props.htmlContent, "<></>");
// setHtml("<p>Hello World</p>");//初始值
setHtml(props.htmlContent); //设置编辑器内容
}, [props.htmlContent]);
// 及时销毁 editor ,重要!
useEffect(() => {
// const toolbar = DomEditor.getToolbar(editor); //查看配置
// console.log("qz-toolbar", toolbar);
return () => {
if (editor == null) {
return;
}
editor.destroy();
setEditor(null);
};
}, [editor]);
return (
<>
<div style={{ border: "1px solid #ccc", zIndex: 100 }}>
<Toolbar
editor={editor}
defaultConfig={toolbarConfig}
mode='default'
style={{ borderBottom: "1px solid #ccc" }}
/>
<Editor
defaultConfig={editorConfig}
value={html}
onCreated={setEditor}
onChange={(editor) => {
// console.log("qz---editor", editor.getHtml());
setHtml(editor.getHtml());
props.onChange(editor.getHtml());// 父组件传一个onChange 方法可以把编辑器的内容存到父组件
}}
mode='default'
style={{ height: "500px", overflowY: "hidden" }}
/>
</div>
{/* <div style={{ marginTop: "15px" }}>{html}</div> */}
</>
);
}
export default MyEditor;
import React, { useState, useEffect } from "react";
import "@wangeditor/editor/dist/css/style.css"; // 引入 cssß
import { Editor, Toolbar } from "@wangeditor/editor-for-react";
import type { IDomEditor, IEditorConfig, IToolbarConfig } from "@wangeditor/editor";
// import { DomEditor } from "@wangeditor/editor";
// import api from "@/api/messageCenter";
// import { message } from "antd";
// import { uchoiceToken, uliveToken } from "@/utils/auth";
import { getUliveAdminBaseUrl } from "@/utils/getBaseUrl";
import type { SlateElement } from "@wangeditor/editor";
export type ImageElement = SlateElement & {
src: string;
alt: string;
url: string;
href: string;
};
export type InsertFnType = (url: string, alt: string, href: string) => void;
function MyEditor(props: any) {
// editor 实例
const [editor, setEditor] = useState<IDomEditor | any>(null); // TS 语法
// 编辑器内容
const [html, setHtml] = useState("");
// 工具栏配置
const toolbarConfig: Partial<IToolbarConfig> = {
//去除的选项
excludeKeys: [
"headerSelect", //正文,标题
"blockquote", //引用
// "|",//隔符
"bold", //加粗
"underline", //下划线
"italic", //斜体
"group-more-style", //样式
"color", //颜色
"bgColor", //背景色
"fontSize", //字体大小
"fontFamily", //字体
// "lineHeight",行高
"bulletedList", //无序列表
"numberedList", //有序列表
"todo", //待办
"group-justify", //对齐
"group-indent", //缩进
// "emotion",//表情
"insertLink", //链接
// "group-image", //图片
"group-video", //视频
"insertTable", //插表格
"codeBlock", //代码块
"divider" //分割线
// "undo",//撤销
// "redo",//重做
// "fullScreen"//全屏
]
};
// 编辑器配置
const editorConfig: Partial<IEditorConfig> = {
placeholder: "请输入内容...",
autoFocus: false,
//插入图片
MENU_CONF: {
uploadImage: {
// 单个文件的最大体积限制,默认为 2M
maxFileSize: 4 * 1024 * 1024, // 4M
// 最多可上传几个文件,默认为 100
maxNumberOfFiles: 10,
// 超时时间,默认为 10 秒
timeout: 5 * 1000, // 5 秒
// 用户自定义上传图片
customUpload(file: any, insertFn: any) {
const axios = require("axios");
const FormData = require("form-data");
const data = new FormData();
data.append("file", file); // file 即选中的文件 主要就是这个传的参数---看接口要携带什么参数{ key :value}
const config = {
method: "post",
url: `${getUliveAdminBaseUrl()}api-base/upload/uploadFile`, //上传图片地址
// headers: {
// "Content-Type": "multipart/form-data",
// Authorization: "Bearer " + uliveToken.get()
// }, //需要加的自己参考接口加
data: data
};
axios(config)
.then(function (res: any) {
console.log("qz-用户自定义上传图片", res);
// const url = "https:// /" + res.data.data.path; //拼接成可浏览的图片地址
insertFn(res.data.result); //插入图片,看返回的数据是什么
})
.catch(function (error: any) {
console.log(error);
});
}
}
}
};
useEffect(() => {
// setHtml("<p>Hello World</p>");
setHtml(props.htmlContent); //设置编辑器内容
}, [props.htmlContent]);
// 及时销毁 editor ,重要!
useEffect(() => {
// const toolbar = DomEditor.getToolbar(editor); //查看配置
// console.log("qz-toolbar", toolbar);
return () => {
if (editor == null) {
return;
}
editor.destroy();
setEditor(null);
};
}, [editor]);
return (
<>
<div style={{ border: "1px solid #ccc", zIndex: 100 }}>
<Toolbar
editor={editor}
defaultConfig={toolbarConfig}
mode='default'
style={{ borderBottom: "1px solid #ccc" }}
/>
<Editor
defaultConfig={editorConfig}
value={html}
onCreated={setEditor}
onChange={(editor) => {
// console.log("qz---editor", editor.getHtml());
//获取纯文本可使用 getText()
setHtml(editor.getHtml());
props.onChange(editor.getHtml());
}}
mode='default'
style={{ height: "500px", overflowY: "hidden" }}
/>
</div>
{/* <div style={{ marginTop: "15px" }}>
{html} //可显示编辑器的内容
</div> */}
</>
);
}
export default MyEditor;