123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- import React, {
- useCallback,
- useEffect,
- useMemo,
- useRef,
- useState,
- } from "react";
- import styles from "./index.module.scss";
- // 引入编辑器组件
- // 安装---npm install braft-editor --save --force
- // npm install braft-utils --save --force
- import { ContentUtils } from "braft-utils";
- import BraftEditor from "braft-editor";
- // 引入编辑器样式
- import "braft-editor/dist/index.css";
- import classNames from "classnames";
- import { MessageFu } from "@/utils/message";
- import { fileDomInitialFu } from "@/utils/domShow";
- import { baseURL } from "@/utils/http";
- import { forwardRef, useImperativeHandle } from "react";
- import { API_upFile } from "@/store/action/layout";
- type Props = {
- check: boolean; //表单校验,为fasle表示不校验
- dirCode: string; //文件的code码
- isLook: boolean; //是否是查看进来
- ref: any; //当前自己的ref,给父组件调用
- myUrl: string; //上传的api地址
- full?: boolean;
- };
- function ZRichText({ check, dirCode, isLook, myUrl, full }: Props, ref: any) {
- // 添加 上传 图片的dom
- useEffect(() => {
- setTimeout(() => {
- const dom = document.querySelector(".bf-controlbar")!;
- const div = document.createElement("div");
- div.className = "upImgBox";
- // div.title = "上传图片";
- div.innerHTML = "上传图片/视频";
- div.onclick = async () => {
- myInput.current?.click();
- };
- dom.appendChild(div);
- }, 20);
- // 监听 富文本 的 class 变化,在全屏的时候会 富文本会添加上 fullscreen 的类
- // 修复顶部样式冲突问题
- const editorDom = document.querySelector(".bf-container") as HTMLDivElement;
- const observer = new MutationObserver(() => {
- // console.log("change");
- const dom = document.querySelector(".layoutRightTop") as HTMLDivElement;
- if (editorDom.className.includes("fullscreen")) dom.style.zIndex = "-1";
- else dom.style.zIndex = "100";
- });
- observer.observe(editorDom, {
- attributes: true,
- });
- // 销毁监听
- return () => {
- observer.disconnect();
- };
- }, []);
- useEffect(() => {
- const controlbarDom = document.querySelectorAll(".txtBox .bf-controlbar ");
- const contentDom = document.querySelectorAll(".txtBox .bf-content ");
- if (controlbarDom) {
- controlbarDom.forEach((v: any) => {
- v.style.display = isLook ? "none" : "block";
- });
- contentDom.forEach((v: any) => {
- v.style.height = isLook ? "100%" : "";
- });
- }
- }, [isLook]);
- // 编辑器文本
- const [editorValue, setEditorValue] = useState(
- // 初始内容
- BraftEditor.createEditorState("")
- );
- // 判断 富文本是否为空
- const isTxtFlag = useMemo(() => {
- const txt: string = editorValue.toHTML();
- if (
- txt.replaceAll("<p>", "").replaceAll("</p>", "").replaceAll(" ", "") ===
- ""
- ) {
- return true;
- } else return false;
- }, [editorValue]);
- const myInput = useRef<HTMLInputElement>(null);
- // 上传图片
- const handeUpPhoto = useCallback(
- async (e: React.ChangeEvent<HTMLInputElement>) => {
- if (e.target.files) {
- // 拿到files信息
- const filesInfo = e.target.files[0];
- let type = ["image/jpeg", "image/png", "video/mp4"];
- let size = 5;
- let txt = "图片只支持png、jpg和jpeg格式!";
- let txt2 = "图片最大支持5M!";
- const isVideoFlag = filesInfo.name.endsWith(".mp4");
- // 校验格式
- if (!type.includes(filesInfo.type)) {
- e.target.value = "";
- if (isVideoFlag) {
- // 上传视频
- size = 500;
- txt = "视频只支持mp4格式!";
- txt2 = "视频最大支持500M!";
- }
- return MessageFu.warning(txt);
- }
- // 校验大小
- if (filesInfo.size > size * 1024 * 1024) {
- e.target.value = "";
- return MessageFu.warning(txt2);
- }
- // 创建FormData对象
- const fd = new FormData();
- // 把files添加进FormData对象(‘photo’为后端需要的字段)
- fd.append("type", isVideoFlag ? "video" : "img");
- fd.append("dirCode", dirCode);
- fd.append("file", filesInfo);
- e.target.value = "";
- try {
- const res = await API_upFile(fd, myUrl);
- if (res.code === 0) {
- MessageFu.success("上传成功!");
- // 在光标位置插入图片
- const newTxt = ContentUtils.insertMedias(editorValue, [
- {
- type: "IMAGE",
- url: baseURL + res.data.filePath,
- },
- ]);
- setEditorValue(newTxt);
- }
- fileDomInitialFu();
- } catch (error) {
- fileDomInitialFu();
- }
- }
- },
- [dirCode, editorValue, myUrl]
- );
- // 让父组件调用的 回显 富文本
- const ritxtShowFu = useCallback((val: string) => {
- setEditorValue(BraftEditor.createEditorState(val));
- }, []);
- // 让父组件调用的返回 富文本信息 和 表单校验 isTxtFlag为ture表示未通过校验
- const fatherBtnOkFu = useCallback(() => {
- return { val: editorValue.toHTML(), flag: isTxtFlag };
- }, [editorValue, isTxtFlag]);
- // 可以让父组件调用子组件的方法
- useImperativeHandle(ref, () => ({
- ritxtShowFu,
- fatherBtnOkFu,
- }));
- return (
- <div className={styles.ZRichText} style={{ width: full ? "100%" : "" }}>
- <input
- id="upInput"
- type="file"
- accept=".png,.jpg,.jpeg,.mp4"
- ref={myInput}
- onChange={(e) => handeUpPhoto(e)}
- />
- <div className="txtBox">
- <BraftEditor
- readOnly={isLook}
- placeholder="请输入内容"
- value={editorValue}
- onChange={(e) => setEditorValue(e)}
- imageControls={["remove"]}
- />
- </div>
- <div
- className={classNames(
- "noUpThumb",
- check && isTxtFlag ? "noUpThumbAc" : ""
- )}
- >
- 请输入正文!
- </div>
- </div>
- );
- }
- export default forwardRef(ZRichText);
|