|
@@ -24,7 +24,7 @@ import { baseURL } from "@/utils/http";
|
|
|
import { forwardRef, useImperativeHandle } from "react";
|
|
|
import { API_upFile } from "@/store/action/layout";
|
|
|
import ZupAudio, { ZupAudioType } from "../ZupAudio";
|
|
|
-import { Button, Checkbox } from "antd";
|
|
|
+import { Button, Checkbox, Input } from "antd";
|
|
|
import {
|
|
|
ArrowDownOutlined,
|
|
|
DeleteOutlined,
|
|
@@ -35,7 +35,7 @@ import MyPopconfirm from "../MyPopconfirm";
|
|
|
export type SectionArrType = {
|
|
|
id: number;
|
|
|
name: string;
|
|
|
- txt: string;
|
|
|
+ txt: any;
|
|
|
fileInfo: ZupAudioType;
|
|
|
};
|
|
|
|
|
@@ -52,11 +52,14 @@ function ZRichTexts({ check, dirCode, isLook, myUrl }: Props, ref: any) {
|
|
|
{
|
|
|
id: Date.now(),
|
|
|
name: "",
|
|
|
- txt: "",
|
|
|
+ txt: BraftEditor.createEditorState(""),
|
|
|
fileInfo: { fileName: "", filePath: "" },
|
|
|
},
|
|
|
]);
|
|
|
|
|
|
+ // 是否按章节发布
|
|
|
+ const [isSection, setIsSection] = useState(false);
|
|
|
+
|
|
|
// 当前上传 图片 视频的索引
|
|
|
const nowIndexRef = useRef(0);
|
|
|
|
|
@@ -64,12 +67,11 @@ function ZRichTexts({ check, dirCode, isLook, myUrl }: Props, ref: any) {
|
|
|
setTimeout(() => {
|
|
|
const domAll = document.querySelectorAll(".bf-controlbar");
|
|
|
const dom = domAll[index];
|
|
|
+
|
|
|
const div = document.createElement("div");
|
|
|
div.className = "upImgBox";
|
|
|
- // div.title = "上传图片";
|
|
|
div.innerHTML = "上传图片/视频";
|
|
|
- div.onclick = async () => {
|
|
|
- nowIndexRef.current = index;
|
|
|
+ div.onclick = () => {
|
|
|
myInput.current?.click();
|
|
|
};
|
|
|
dom.appendChild(div);
|
|
@@ -79,6 +81,7 @@ function ZRichTexts({ check, dirCode, isLook, myUrl }: Props, ref: any) {
|
|
|
// 为富文本添加 上传图片/视频 的dom
|
|
|
useEffect(() => {
|
|
|
addDomFu(sectionArr.length - 1);
|
|
|
+ // 新增的富文本 也要初始化数据
|
|
|
}, [addDomFu, sectionArr.length]);
|
|
|
|
|
|
// useEffect(() => {
|
|
@@ -95,21 +98,40 @@ function ZRichTexts({ check, dirCode, isLook, myUrl }: Props, ref: any) {
|
|
|
// }, [isLook]);
|
|
|
|
|
|
// 编辑器文本
|
|
|
- const [editorValue, setEditorValue] = useState(
|
|
|
- // 初始内容
|
|
|
- BraftEditor.createEditorState("")
|
|
|
- );
|
|
|
+ // const [editorValue, setEditorValue] = useState<any[]>(
|
|
|
+ // // 初始内容
|
|
|
+ // [BraftEditor.createEditorState("")]
|
|
|
+ // );
|
|
|
|
|
|
// 判断 富文本是否为空
|
|
|
const isTxtFlag = useMemo(() => {
|
|
|
- const txt: string = editorValue.toHTML();
|
|
|
- if (
|
|
|
- txt.replaceAll("<p>", "").replaceAll("</p>", "").replaceAll(" ", "") ===
|
|
|
- ""
|
|
|
- ) {
|
|
|
- return true;
|
|
|
- } else return false;
|
|
|
- }, [editorValue]);
|
|
|
+ let flag = false;
|
|
|
+
|
|
|
+ // 不是按章节发布,检查第一个富文本
|
|
|
+ if (!isSection) {
|
|
|
+ const txt = sectionArr[0].txt.toHTML();
|
|
|
+ if (
|
|
|
+ txt.replaceAll("<p>", "").replaceAll("</p>", "").replaceAll(" ", "") ===
|
|
|
+ ""
|
|
|
+ )
|
|
|
+ flag = true;
|
|
|
+ } else {
|
|
|
+ // 按章节发布 检查 所有的 标题 和富文本
|
|
|
+ sectionArr.forEach((v, i) => {
|
|
|
+ if (!v.name) flag = true;
|
|
|
+ const txt: string = v.txt.toHTML();
|
|
|
+ if (
|
|
|
+ txt
|
|
|
+ .replaceAll("<p>", "")
|
|
|
+ .replaceAll("</p>", "")
|
|
|
+ .replaceAll(" ", "") === ""
|
|
|
+ )
|
|
|
+ flag = true;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ return flag;
|
|
|
+ }, [isSection, sectionArr]);
|
|
|
|
|
|
const myInput = useRef<HTMLInputElement>(null);
|
|
|
|
|
@@ -158,14 +180,18 @@ function ZRichTexts({ check, dirCode, isLook, myUrl }: Props, ref: any) {
|
|
|
if (res.code === 0) {
|
|
|
MessageFu.success("上传成功!");
|
|
|
// 在光标位置插入图片
|
|
|
- const newTxt = ContentUtils.insertMedias(editorValue, [
|
|
|
- {
|
|
|
- type: "IMAGE",
|
|
|
- url: baseURL + res.data.filePath,
|
|
|
- },
|
|
|
- ]);
|
|
|
-
|
|
|
- setEditorValue(newTxt);
|
|
|
+ const newTxt = ContentUtils.insertMedias(
|
|
|
+ sectionArr[nowIndexRef.current].txt,
|
|
|
+ [
|
|
|
+ {
|
|
|
+ type: isVideoFlag ? "VIDEO" : "IMAGE",
|
|
|
+ url: baseURL + res.data.filePath,
|
|
|
+ },
|
|
|
+ ]
|
|
|
+ );
|
|
|
+ const arr = [...sectionArr];
|
|
|
+ arr[nowIndexRef.current].txt = newTxt;
|
|
|
+ setSectionArr(arr);
|
|
|
}
|
|
|
fileDomInitialFu();
|
|
|
} catch (error) {
|
|
@@ -173,18 +199,41 @@ function ZRichTexts({ check, dirCode, isLook, myUrl }: Props, ref: any) {
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
- [dirCode, editorValue, myUrl]
|
|
|
+ [dirCode, myUrl, sectionArr]
|
|
|
);
|
|
|
|
|
|
// 让父组件调用的 回显 富文本
|
|
|
- const ritxtShowFu = useCallback((val: string) => {
|
|
|
- setEditorValue(BraftEditor.createEditorState(val));
|
|
|
+ const ritxtShowFu = useCallback((val: any) => {
|
|
|
+ if (val) {
|
|
|
+ setIsSection(val.isSection || false);
|
|
|
+ if (val.txtArr) {
|
|
|
+ const arr = val.txtArr.map((v: any) => ({
|
|
|
+ ...v,
|
|
|
+ txt: BraftEditor.createEditorState(v.txt),
|
|
|
+ }));
|
|
|
+ setSectionArr(arr);
|
|
|
+ }
|
|
|
+ }
|
|
|
}, []);
|
|
|
|
|
|
// 让父组件调用的返回 富文本信息 和 表单校验 isTxtFlag为ture表示未通过校验
|
|
|
const fatherBtnOkFu = useCallback(() => {
|
|
|
- return { val: editorValue.toHTML(), flag: isTxtFlag };
|
|
|
- }, [editorValue, isTxtFlag]);
|
|
|
+ const arr: any[] = [];
|
|
|
+
|
|
|
+ sectionArr.forEach((v, i) => {
|
|
|
+ arr.push({
|
|
|
+ ...v,
|
|
|
+ txt: v.txt.toHTML(),
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ const obj = {
|
|
|
+ isSection: isSection, //是否按章节发布
|
|
|
+ txtArr: arr,
|
|
|
+ };
|
|
|
+
|
|
|
+ return { val: obj, flag: isTxtFlag };
|
|
|
+ }, [isSection, isTxtFlag, sectionArr]);
|
|
|
|
|
|
// 可以让父组件调用子组件的方法
|
|
|
useImperativeHandle(ref, () => ({
|
|
@@ -192,20 +241,17 @@ function ZRichTexts({ check, dirCode, isLook, myUrl }: Props, ref: any) {
|
|
|
fatherBtnOkFu,
|
|
|
}));
|
|
|
|
|
|
- // 是否按章节发布
|
|
|
- const [isSection, setIsSection] = useState(false);
|
|
|
-
|
|
|
// 点击新增章节
|
|
|
const addSectionFu = useCallback(() => {
|
|
|
if (sectionArr.length >= 20) return MessageFu.warning("最多存在20个章节");
|
|
|
setSectionArr([
|
|
|
+ ...sectionArr,
|
|
|
{
|
|
|
id: Date.now(),
|
|
|
name: "",
|
|
|
- txt: "",
|
|
|
+ txt: BraftEditor.createEditorState(""),
|
|
|
fileInfo: { fileName: "", filePath: "" },
|
|
|
},
|
|
|
- ...sectionArr,
|
|
|
]);
|
|
|
}, [sectionArr]);
|
|
|
|
|
@@ -242,13 +288,31 @@ function ZRichTexts({ check, dirCode, isLook, myUrl }: Props, ref: any) {
|
|
|
(index: number, num: number) => {
|
|
|
const arr = [...sectionArr];
|
|
|
const temp = arr[index];
|
|
|
- arr[index] = arr[index + 1];
|
|
|
- arr[index + 1] = temp;
|
|
|
+ arr[index] = arr[index + num];
|
|
|
+ arr[index + num] = temp;
|
|
|
setSectionArr(arr);
|
|
|
},
|
|
|
[sectionArr]
|
|
|
);
|
|
|
|
|
|
+ // 单个富文本是否输入完整
|
|
|
+ const isOneTxtFlag = useCallback(
|
|
|
+ (name: string, txt: any) => {
|
|
|
+ let flag = false;
|
|
|
+ if (!name && isSection) flag = true;
|
|
|
+ const txtRes: string = txt.toHTML();
|
|
|
+ if (
|
|
|
+ txtRes
|
|
|
+ .replaceAll("<p>", "")
|
|
|
+ .replaceAll("</p>", "")
|
|
|
+ .replaceAll(" ", "") === ""
|
|
|
+ )
|
|
|
+ flag = true;
|
|
|
+ return flag;
|
|
|
+ },
|
|
|
+ [isSection]
|
|
|
+ );
|
|
|
+
|
|
|
return (
|
|
|
<div className={styles.ZRichTexts}>
|
|
|
<input
|
|
@@ -285,10 +349,35 @@ function ZRichTexts({ check, dirCode, isLook, myUrl }: Props, ref: any) {
|
|
|
|
|
|
<div className="txtBox">
|
|
|
{sectionArr.map((item, index) => (
|
|
|
- <div className="zztxtRow" key={item.id}>
|
|
|
+ <div
|
|
|
+ className={classNames(
|
|
|
+ "zztxtRow",
|
|
|
+ isOneTxtFlag(item.name, item.txt) && check ? "zztxtRowErr" : ""
|
|
|
+ )}
|
|
|
+ key={item.id}
|
|
|
+ hidden={!isSection && index > 0}
|
|
|
+ onMouseOver={() => (nowIndexRef.current = index)}
|
|
|
+ >
|
|
|
{/* 顶部 */}
|
|
|
- <div className="zztxtRow1">
|
|
|
- <div className="zztxtRow1_1">章节1</div>
|
|
|
+ <div className="zztxtRow1" hidden={!isSection && index === 0}>
|
|
|
+ <div className="zztxtRow1_1">
|
|
|
+ <div className="zztxtRow1_1_1">章节 {index + 1}</div>
|
|
|
+ <div className="zztxtRow1_1_2">
|
|
|
+ 标题:
|
|
|
+ <Input
|
|
|
+ value={item.name}
|
|
|
+ placeholder="请输入内容"
|
|
|
+ maxLength={30}
|
|
|
+ showCount
|
|
|
+ style={{ width: 500 }}
|
|
|
+ onChange={(e) => {
|
|
|
+ const arr = [...sectionArr];
|
|
|
+ arr[index].name = e.target.value.replace(/\s+/g, "");
|
|
|
+ setSectionArr(arr);
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
<div className="zztxtRow1_2">
|
|
|
<ZupAudio
|
|
|
fileInfo={item.fileInfo}
|
|
@@ -330,8 +419,12 @@ function ZRichTexts({ check, dirCode, isLook, myUrl }: Props, ref: any) {
|
|
|
<BraftEditor
|
|
|
readOnly={isLook}
|
|
|
placeholder="请输入内容"
|
|
|
- value={editorValue}
|
|
|
- onChange={(e) => setEditorValue(e)}
|
|
|
+ value={item.txt}
|
|
|
+ onChange={(e) => {
|
|
|
+ const arr = [...sectionArr];
|
|
|
+ arr[index].txt = e;
|
|
|
+ setSectionArr(arr);
|
|
|
+ }}
|
|
|
imageControls={["remove"]}
|
|
|
/>
|
|
|
</div>
|
|
@@ -343,7 +436,7 @@ function ZRichTexts({ check, dirCode, isLook, myUrl }: Props, ref: any) {
|
|
|
check && isTxtFlag ? "noUpThumbAc" : ""
|
|
|
)}
|
|
|
>
|
|
|
- 请完整输入正文!
|
|
|
+ {`请完整输入${isSection ? "标题/" : ""}正文!`}
|
|
|
</div>
|
|
|
</div>
|
|
|
);
|