shaogen1995 1 год назад
Родитель
Сommit
516cdaddf0

+ 21 - 7
src/components/ZRichText/index.tsx

@@ -41,7 +41,7 @@ function ZRichText({ check, dirCode, isLook, myUrl, full }: Props, ref: any) {
       const div = document.createElement("div");
       div.className = "upImgBox";
       // div.title = "上传图片";
-      div.innerHTML = "上传图片";
+      div.innerHTML = "上传图片/视频";
       div.onclick = async () => {
         myInput.current?.click();
       };
@@ -109,21 +109,35 @@ function ZRichText({ check, dirCode, isLook, myUrl, full }: Props, ref: any) {
       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");
+
         // 校验格式
-        const type = ["image/jpeg", "image/png"];
         if (!type.includes(filesInfo.type)) {
           e.target.value = "";
-          return MessageFu.warning("只支持png、jpg和jpeg格式!");
+          if (isVideoFlag) {
+            // 上传视频
+            size = 500;
+            txt = "视频只支持mp4格式!";
+            txt2 = "视频最大支持500M!";
+          }
+
+          return MessageFu.warning(txt);
         }
         // 校验大小
-        if (filesInfo.size > 5 * 1024 * 1024) {
+        if (filesInfo.size > size * 1024 * 1024) {
           e.target.value = "";
-          return MessageFu.warning("最大支持5M!");
+          return MessageFu.warning(txt2);
         }
         // 创建FormData对象
         const fd = new FormData();
         // 把files添加进FormData对象(‘photo’为后端需要的字段)
-        fd.append("type", "img");
+        fd.append("type", isVideoFlag ? "video" : "img");
         fd.append("dirCode", dirCode);
         fd.append("file", filesInfo);
 
@@ -173,7 +187,7 @@ function ZRichText({ check, dirCode, isLook, myUrl, full }: Props, ref: any) {
       <input
         id="upInput"
         type="file"
-        accept=".png,.jpg,.jpeg"
+        accept=".png,.jpg,.jpeg,.mp4"
         ref={myInput}
         onChange={(e) => handeUpPhoto(e)}
       />

+ 50 - 5
src/components/ZRichTexts/index.module.scss

@@ -1,14 +1,23 @@
 .ZRichTexts {
   width: 1000px;
-  height: 100%;
 
   :global {
+
+    // 正文
+    .formRightZW {
+      width: 700px;
+      top: -3px;
+      position: relative;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+    }
+
     .txtBox {
       width: 100%;
-      height: 100%;
       border: 1px solid #ccc;
 
-      a{
+      a {
         color: #fff !important;
       }
 
@@ -18,11 +27,11 @@
       }
 
       .bf-container {
-        height:100%;
+        height: 100%;
       }
 
       .bf-content {
-        height: calc(100% - 92px);
+        max-height: 300px;
         padding-bottom: 0px;
       }
 
@@ -45,6 +54,42 @@
         }
 
       }
+
+      .zztxtRow {
+        .zztxtRow1 {
+          padding: 0 20px;
+          height: 40px;
+          display: flex;
+          align-items: center;
+          justify-content: space-between;
+          background-color: #e8e8e8;
+
+          .zztxtRow1_1 {
+            font-weight: 700;
+            font-size: 16px;
+          }
+        }
+
+        .zztxtRow1_2 {
+          display: flex;
+          align-items: center;
+
+          .anticon {
+            cursor: pointer;
+            font-size: 18px;
+          }
+
+          .zztxtRow1_2Icon {
+            position: relative;
+            top: 2px;
+          }
+
+          .zztxtRow1_2IconNo {
+            pointer-events: none;
+            opacity: .2;
+          }
+        }
+      }
     }
 
     .noUpThumb {

+ 204 - 54
src/components/ZRichTexts/index.tsx

@@ -23,6 +23,21 @@ 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 {
+  ArrowDownOutlined,
+  DeleteOutlined,
+  ArrowUpOutlined,
+} from "@ant-design/icons";
+import MyPopconfirm from "../MyPopconfirm";
+
+export type SectionArrType = {
+  id: number;
+  name: string;
+  txt: string;
+  fileInfo: ZupAudioType;
+};
 
 type Props = {
   check: boolean; //表单校验,为fasle表示不校验
@@ -30,59 +45,54 @@ type Props = {
   isLook: boolean; //是否是查看进来
   ref: any; //当前自己的ref,给父组件调用
   myUrl: string; //上传的api地址
-  full?: boolean;
 };
 
-function ZRichTexts({ check, dirCode, isLook, myUrl, full }: Props, ref: any) {
-  // 添加 上传 图片的dom
-  useEffect(() => {
+function ZRichTexts({ check, dirCode, isLook, myUrl }: Props, ref: any) {
+  const [sectionArr, setSectionArr] = useState<SectionArrType[]>([
+    {
+      id: Date.now(),
+      name: "",
+      txt: "",
+      fileInfo: { fileName: "", filePath: "" },
+    },
+  ]);
+
+  // 当前上传 图片 视频的索引
+  const nowIndexRef = useRef(0);
+
+  const addDomFu = useCallback((index: number) => {
     setTimeout(() => {
-      const dom = document.querySelector(".bf-controlbar")!;
+      const domAll = document.querySelectorAll(".bf-controlbar");
+      const dom = domAll[index];
       const div = document.createElement("div");
       div.className = "upImgBox";
       // div.title = "上传图片";
-      div.innerHTML = "上传图片";
+      div.innerHTML = "上传图片/视频";
       div.onclick = async () => {
+        nowIndexRef.current = index;
         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();
-    };
   }, []);
 
+  // 为富文本添加 上传图片/视频 的dom
   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]);
+    addDomFu(sectionArr.length - 1);
+  }, [addDomFu, sectionArr.length]);
+
+  // 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(
@@ -109,21 +119,35 @@ function ZRichTexts({ check, dirCode, isLook, myUrl, full }: Props, ref: any) {
       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");
+
         // 校验格式
-        const type = ["image/jpeg", "image/png"];
         if (!type.includes(filesInfo.type)) {
           e.target.value = "";
-          return MessageFu.warning("只支持png、jpg和jpeg格式!");
+          if (isVideoFlag) {
+            // 上传视频
+            size = 500;
+            txt = "视频只支持mp4格式!";
+            txt2 = "视频最大支持500M!";
+          }
+
+          return MessageFu.warning(txt);
         }
         // 校验大小
-        if (filesInfo.size > 5 * 1024 * 1024) {
+        if (filesInfo.size > size * 1024 * 1024) {
           e.target.value = "";
-          return MessageFu.warning("最大支持5M!");
+          return MessageFu.warning(txt2);
         }
         // 创建FormData对象
         const fd = new FormData();
         // 把files添加进FormData对象(‘photo’为后端需要的字段)
-        fd.append("type", "img");
+        fd.append("type", isVideoFlag ? "video" : "img");
         fd.append("dirCode", dirCode);
         fd.append("file", filesInfo);
 
@@ -168,24 +192,150 @@ function ZRichTexts({ check, dirCode, isLook, myUrl, full }: Props, ref: any) {
     fatherBtnOkFu,
   }));
 
+  // 是否按章节发布
+  const [isSection, setIsSection] = useState(false);
+
+  // 点击新增章节
+  const addSectionFu = useCallback(() => {
+    if (sectionArr.length >= 20) return MessageFu.warning("最多存在20个章节");
+    setSectionArr([
+      {
+        id: Date.now(),
+        name: "",
+        txt: "",
+        fileInfo: { fileName: "", filePath: "" },
+      },
+      ...sectionArr,
+    ]);
+  }, [sectionArr]);
+
+  // 章节音频上传成功
+  const upSectionFu = useCallback(
+    (info: ZupAudioType, index: number) => {
+      const arr = [...sectionArr];
+      arr[index].fileInfo = info;
+      setSectionArr(arr);
+    },
+    [sectionArr]
+  );
+
+  // 章节音频删除
+  const delSectionFu = useCallback(
+    (index: number) => {
+      const arr = [...sectionArr];
+      arr[index].fileInfo = {} as ZupAudioType;
+      setSectionArr(arr);
+    },
+    [sectionArr]
+  );
+
+  // 整个章节的删除
+  const delSectionAllFu = useCallback(
+    (id: number) => {
+      setSectionArr(sectionArr.filter((v) => v.id !== id));
+    },
+    [sectionArr]
+  );
+
+  // 整个章节的位移
+  const moveSectionFu = useCallback(
+    (index: number, num: number) => {
+      const arr = [...sectionArr];
+      const temp = arr[index];
+      arr[index] = arr[index + 1];
+      arr[index + 1] = temp;
+      setSectionArr(arr);
+    },
+    [sectionArr]
+  );
+
   return (
-    <div className={styles.ZRichTexts} style={{ width: full ? "100%" : "" }}>
+    <div className={styles.ZRichTexts}>
       <input
         id="upInput"
         type="file"
-        accept=".png,.jpg,.jpeg"
+        accept=".png,.jpg,.jpeg,.mp4"
         ref={myInput}
         onChange={(e) => handeUpPhoto(e)}
       />
 
+      <div className="formRightZW">
+        <Checkbox
+          checked={isSection}
+          onChange={(e) => setIsSection(e.target.checked)}
+        >
+          按章节发布
+        </Checkbox>
+
+        {isSection ? (
+          <Button type="primary" onClick={addSectionFu}>
+            新增章节
+          </Button>
+        ) : (
+          <ZupAudio
+            fileInfo={sectionArr[0].fileInfo}
+            upDataFu={(info) => upSectionFu(info, 0)}
+            delFu={() => delSectionFu(0)}
+            dirCode={dirCode}
+            myUrl="cms/event/upload"
+            isLook={isLook}
+          />
+        )}
+      </div>
+
       <div className="txtBox">
-        <BraftEditor
-          readOnly={isLook}
-          placeholder="请输入内容"
-          value={editorValue}
-          onChange={(e) => setEditorValue(e)}
-          imageControls={["remove"]}
-        />
+        {sectionArr.map((item, index) => (
+          <div className="zztxtRow" key={item.id}>
+            {/* 顶部 */}
+            <div className="zztxtRow1">
+              <div className="zztxtRow1_1">章节1</div>
+              <div className="zztxtRow1_2">
+                <ZupAudio
+                  fileInfo={item.fileInfo}
+                  upDataFu={(info, index) => upSectionFu(info, index)}
+                  delFu={(index) => delSectionFu(index)}
+                  dirCode={dirCode}
+                  myUrl="cms/event/upload"
+                  isLook={isLook}
+                />
+                &emsp;
+                <div
+                  className={classNames(
+                    "zztxtRow1_2Icon",
+                    index === 0 ? "zztxtRow1_2IconNo" : ""
+                  )}
+                  onClick={() => moveSectionFu(index, -1)}
+                >
+                  <ArrowUpOutlined title="上移" />
+                </div>
+                &emsp;
+                <div
+                  className={classNames(
+                    "zztxtRow1_2Icon",
+                    index === sectionArr.length - 1 ? "zztxtRow1_2IconNo" : ""
+                  )}
+                  onClick={() => moveSectionFu(index, 1)}
+                >
+                  <ArrowDownOutlined title="下移" />
+                </div>
+                &emsp;
+                <MyPopconfirm
+                  txtK="删除"
+                  onConfirm={() => delSectionAllFu(item.id)}
+                  Dom={<DeleteOutlined title="删除" className="ZTbox2X" />}
+                />
+              </div>
+            </div>
+            {/* 主体 */}
+            <BraftEditor
+              readOnly={isLook}
+              placeholder="请输入内容"
+              value={editorValue}
+              onChange={(e) => setEditorValue(e)}
+              imageControls={["remove"]}
+            />
+          </div>
+        ))}
       </div>
       <div
         className={classNames(
@@ -193,7 +343,7 @@ function ZRichTexts({ check, dirCode, isLook, myUrl, full }: Props, ref: any) {
           check && isTxtFlag ? "noUpThumbAc" : ""
         )}
       >
-        请输入正文!
+        请完整输入正文!
       </div>
     </div>
   );

+ 1 - 0
src/components/ZupAudio/index.module.scss

@@ -7,6 +7,7 @@
   // top: -4px;
   border: 1px solid #ccc;
   border-radius: 16px;
+  background-color: #fff;
 
   :global {
 

+ 1 - 1
src/components/ZupAudio/index.tsx

@@ -39,7 +39,7 @@ function ZupAudio({
       if (e.target.files) {
         // 拿到files信息
         const filesInfo = e.target.files[0];
-        // console.log("-----", filesInfo.type);
+        // console.log("-----", filesInfo);
 
         // 校验格式
         const type = ["audio/mpeg"];

+ 1 - 9
src/pages/A1event/A1add/index.module.scss

@@ -46,15 +46,7 @@
             width: calc(100% - 100px);
           }
         }
-        // 正文
-        .formRightZW{
-          top: -3px;
-          position: relative;
-          width: 100%;
-          display: flex;
-          align-items: center;
-          justify-content: space-between;
-        }
+
 
         .A1Ebtn {
           position: absolute;

+ 8 - 94
src/pages/A1event/A1add/index.tsx

@@ -8,6 +8,7 @@ import { MessageFu } from "@/utils/message";
 import MyPopconfirm from "@/components/MyPopconfirm";
 import ZupAudio, { ZupAudioType } from "@/components/ZupAudio";
 import ZupOne from "@/components/ZupOne";
+import ZRichTexts, { SectionArrType } from "@/components/ZRichTexts";
 
 type Props = {
   editInfo: A1EditInfoType;
@@ -71,78 +72,7 @@ function A1add({ editInfo, closeFu, editTableFu, addTableFu }: Props) {
   // 附件 是否 已经点击过确定
   const [fileCheck, setFileCheck] = useState(false);
 
-  // 是否按章节发布
-  const [isSection, setIsSection] = useState(false);
 
-  type SectionArrType = {
-    id: number;
-    name: string;
-    txt: string;
-    fileInfo: ZupAudioType;
-  };
-
-  const [sectionArr, setSectionArr] = useState<SectionArrType[]>([
-    {
-      id: Date.now(),
-      name: "",
-      txt: "",
-      fileInfo: { fileName: "", filePath: "" },
-    },
-  ]);
-
-  // 点击新增章节
-  const addSectionFu = useCallback(() => {
-    if (sectionArr.length >= 20) return MessageFu.warning("最多存在20个章节");
-    setSectionArr([
-      {
-        id: Date.now(),
-        name: "",
-        txt: "",
-        fileInfo: { fileName: "", filePath: "" },
-      },
-      ...sectionArr,
-    ]);
-  }, [sectionArr]);
-
-  // 章节音频上传成功
-  const upSectionFu = useCallback(
-    (info: ZupAudioType, index: number) => {
-      const arr = [...sectionArr];
-      arr[index].fileInfo = info;
-      setSectionArr(arr);
-    },
-    [sectionArr]
-  );
-
-  // 章节音频删除
-  const delSectionFu = useCallback(
-    (index: number) => {
-      const arr = [...sectionArr];
-      arr[index].fileInfo = {} as ZupAudioType;
-      setSectionArr(arr);
-    },
-    [sectionArr]
-  );
-
-  // 整个章节的删除
-  const delSectionAllFu = useCallback(
-    (id: number) => {
-      setSectionArr(sectionArr.filter((v) => v.id !== id));
-    },
-    [sectionArr]
-  );
-
-  // 整个章节的位移
-  const moveSectionFu = useCallback(
-    (index: number, num: number) => {
-      const arr = [...sectionArr];
-      const temp = arr[index];
-      arr[index] = arr[index + 1];
-      arr[index + 1] = temp;
-      setSectionArr(arr);
-    },
-    [sectionArr]
-  );
 
   // 没有通过校验
   const onFinishFailed = useCallback(() => {
@@ -254,29 +184,13 @@ function A1add({ editInfo, closeFu, editTableFu, addTableFu }: Props) {
               正文:
             </div>
             <div className="formRight">
-              <div className="formRightZW">
-                <Checkbox
-                  checked={isSection}
-                  onChange={(e) => setIsSection(e.target.checked)}
-                >
-                  按章节发布
-                </Checkbox>
-
-                {isSection ? (
-                  <Button type="primary" onClick={addSectionFu}>
-                    新增章节
-                  </Button>
-                ) : (
-                  <ZupAudio
-                    fileInfo={sectionArr[0].fileInfo}
-                    upDataFu={(info) => upSectionFu(info, 0)}
-                    delFu={() => delSectionFu(0)}
-                    dirCode={dirCode}
-                    myUrl="cms/event/upload"
-                    isLook={editInfo.txt === "查看"}
-                  />
-                )}
-              </div>
+              <ZRichTexts
+                check={fileCheck}
+                dirCode={dirCode}
+                isLook={editInfo.txt === "查看"}
+                ref={ZRichTextRef}
+                myUrl="cms/event/upload"
+              />
             </div>
           </div>
 

+ 1 - 8
src/pages/Layout/index.module.scss

@@ -58,14 +58,7 @@
             background-color: var(--themeColor);
           }
         }
-
-
-
-
-
       }
-
-
     }
 
     .layoutRight {
@@ -78,7 +71,7 @@
         display: flex;
         justify-content: flex-end;
         position: relative;
-        z-index: 1000;
+        // z-index: 1000;
 
         .user {
           margin-right: 40px;