Browse Source

搞不动了

shaogen1995 1 năm trước cách đây
mục cha
commit
80f45f42c3

+ 25 - 7
src/components/ZRichTexts/index.module.scss

@@ -15,7 +15,7 @@
 
     .txtBox {
       width: 100%;
-      border: 1px solid #ccc;
+      position: relative;
 
       a {
         color: #fff !important;
@@ -31,7 +31,7 @@
       }
 
       .bf-content {
-        max-height: 300px;
+        height: 300px;
         padding-bottom: 0px;
       }
 
@@ -56,6 +56,9 @@
       }
 
       .zztxtRow {
+        margin-bottom: 20px;
+        border: 1px solid #ccc;
+
         .zztxtRow1 {
           padding: 0 20px;
           height: 40px;
@@ -65,8 +68,18 @@
           background-color: #e8e8e8;
 
           .zztxtRow1_1 {
-            font-weight: 700;
-            font-size: 16px;
+            display: flex;
+
+            .zztxtRow1_1_1 {
+              font-weight: 700;
+              font-size: 16px;
+              margin-right: 20px;
+            }
+
+            .zztxtRow1_1_2 {
+              width: 550px;
+            }
+
           }
         }
 
@@ -90,6 +103,9 @@
           }
         }
       }
+      .zztxtRowErr{
+        border-color: #ff4d4f;
+      }
     }
 
     .noUpThumb {
@@ -98,18 +114,18 @@
       opacity: 0;
       transition: top .2s;
       color: #ff4d4f;
-      top: -10px;
+      top: -20px;
     }
 
     .noUpThumbAc {
-      top: 0;
+      top: -10px;
       opacity: 1;
     }
 
     .bf-media .bf-image {
       float: initial !important;
       display: block;
-      margin: 10px auto;
+      margin: 0px auto;
       text-align: center;
 
       // 不让拖动放大缩小图片(会报错)
@@ -123,5 +139,7 @@
       }
     }
 
+    // .bf-video-wrap 
+
   }
 }

+ 137 - 44
src/components/ZRichTexts/index.tsx

@@ -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>
   );

+ 7 - 3
src/pages/A1event/A1add/index.module.scss

@@ -15,10 +15,14 @@
       height: 100%;
       overflow-y: auto;
 
-      .A1Frow {
+      .A1_1Frow {
+        position: relative;
+      }
+
+      .A1_1_1Frow {
         position: absolute;
-        top: 24px;
-        left: 624px;
+        top: 0px;
+        left: 500px;
         width: 200px;
       }
 

+ 21 - 20
src/pages/A1event/A1add/index.tsx

@@ -72,8 +72,6 @@ function A1add({ editInfo, closeFu, editTableFu, addTableFu }: Props) {
   // 附件 是否 已经点击过确定
   const [fileCheck, setFileCheck] = useState(false);
 
-
-
   // 没有通过校验
   const onFinishFailed = useCallback(() => {
     setFileCheck(true);
@@ -129,31 +127,33 @@ function A1add({ editInfo, closeFu, editTableFu, addTableFu }: Props) {
           scrollToFirstError
         >
           <Form.Item
+            className="A1_1Frow"
             label="标题"
             name="name"
             rules={[{ required: true, message: "请输入标题!" }]}
             getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
           >
-            <Input
-              style={{ width: "500px" }}
-              maxLength={50}
-              showCount
-              placeholder="请输入内容"
-            />
+            <div>
+              <Input
+                style={{ width: "500px" }}
+                maxLength={50}
+                showCount
+                placeholder="请输入内容"
+              />
+              {/* 标题的无障碍音频 */}
+              <div className="A1_1_1Frow">
+                <ZupAudio
+                  fileInfo={nameAudio}
+                  upDataFu={(info) => setNameAudio(info)}
+                  delFu={() => setNameAudio({} as ZupAudioType)}
+                  dirCode={dirCode}
+                  myUrl="cms/event/upload"
+                  isLook={editInfo.txt === "查看"}
+                />
+              </div>
+            </div>
           </Form.Item>
 
-          {/* 标题的无障碍音频 */}
-          <div className="A1Frow">
-            <ZupAudio
-              fileInfo={nameAudio}
-              upDataFu={(info) => setNameAudio(info)}
-              delFu={() => setNameAudio({} as ZupAudioType)}
-              dirCode={dirCode}
-              myUrl="cms/event/upload"
-              isLook={editInfo.txt === "查看"}
-            />
-          </div>
-
           {/* 封面 */}
           <div className="formRow">
             <div className="formLeft">
@@ -186,6 +186,7 @@ function A1add({ editInfo, closeFu, editTableFu, addTableFu }: Props) {
             <div className="formRight">
               <ZRichTexts
                 check={fileCheck}
+                // check={true}
                 dirCode={dirCode}
                 isLook={editInfo.txt === "查看"}
                 ref={ZRichTextRef}

+ 22 - 35
src/pages/Layout/index.module.scss

@@ -23,6 +23,7 @@
 
       .layoutLeftMain {
         padding-top: 30px;
+
         .layoutLRowBox {
           .layoutLRowBoxTxt {
             font-size: 18px;
@@ -64,27 +65,28 @@
     .layoutRight {
       width: calc(100% - 220px);
       height: 100%;
+      overflow: hidden;
 
 
       .layoutRightTop {
         height: 60px;
-        display: flex;
-        justify-content: flex-end;
         position: relative;
-        // z-index: 1000;
 
         .user {
-          margin-right: 40px;
-          padding-right: 40px;
+          position: absolute;
+          right: -150px;
+          top: 0;
+          height: 100%;
           display: flex;
           align-items: center;
-          padding-left: 55px;
           cursor: pointer;
-          position: relative;
           background: url('../../assets/img/user.png') no-repeat left center;
           background-size: 40px 40px;
+          padding-left: 45px;
           font-size: 16px;
           color: black;
+          transition: all .3s;
+
 
           .userInco {
             margin-left: 10px;
@@ -92,34 +94,31 @@
           }
 
           .userInco1 {
-            display: none;
+            // display: none;
+            opacity: 0 !important;
           }
 
           .userSet {
+            position: relative;
+            top: 10px;
+            margin-left: 40px;
             width: 140px;
-            opacity: 0;
-            pointer-events: none;
-            transition: bottom .3s;
-            height: 120px;
-            position: absolute;
-            left: 50%;
-            transform: translateX(-50%);
-            bottom: -80px;
-
-            // color: rgb(226, 223, 223);
+            opacity: 1;
+            height: 74px;
+
             &>div {
               box-shadow: 1px 1px 4px 4px #ccc;
-              margin-top: 15px;
               border-radius: 10px;
               overflow: hidden;
 
+
               &>span {
                 background-color: #fff;
                 display: block;
                 width: 100%;
-                height: 50px;
-                line-height: 50px;
                 text-align: center;
+                height: 35px;
+                line-height: 35px;
 
                 &:hover {
                   color: var(--themeColor);
@@ -130,20 +129,8 @@
           }
 
           &:hover {
-            .userSet {
-              opacity: 1;
-              pointer-events: auto;
-              bottom: -120px;
-            }
-
-            .userInco1 {
-              display: block;
-            }
-
-            .userInco2 {
-              display: none;
-            }
-
+     
+            right: 20px;
 
           }
         }

+ 5 - 5
src/pages/Layout/index.tsx

@@ -1,5 +1,5 @@
 import React, { useCallback, useEffect, useRef, useState } from "react";
-import { CaretUpOutlined, CaretDownOutlined } from "@ant-design/icons";
+import { CaretLeftOutlined, CaretRightOutlined } from "@ant-design/icons";
 import styles from "./index.module.scss";
 import SpinLoding from "@/components/SpinLoding";
 import { Route, Switch, useLocation } from "react-router-dom";
@@ -191,11 +191,11 @@ function Layout() {
             {getTokenInfo().user.realName ||
               getTokenInfo().user.userName ||
               "匿名"}
-            <div className="userInco userInco1">
-              <CaretUpOutlined rev={undefined} />
-            </div>
+            {/* <div className="userInco userInco1">
+              <CaretLeftOutlined />
+            </div> */}
             <div className="userInco userInco2">
-              <CaretDownOutlined rev={undefined} />
+              <CaretRightOutlined />
             </div>
             <div className="userSet">
               <div>