Bläddra i källkod

学习参与模块(真鸡儿难写)

shaogen1995 1 år sedan
förälder
incheckning
9c44854eed

+ 4 - 3
src/assets/styles/base.less

@@ -70,7 +70,7 @@ textarea {
 }
 
 // 气泡框闪烁问题
-.ant-popconfirm{
+.ant-popconfirm {
   width: 240px;
 }
 
@@ -237,7 +237,8 @@ textarea {
 #upInput2 {
   display: none;
 }
-#upInputAudio{
+
+#upInputAudio {
   display: none;
 }
 
@@ -283,4 +284,4 @@ textarea {
   -webkit-box-shadow: inset 0 0 5px transparent;
   border-radius: 10px;
   background: transparent;
-}
+}

+ 14 - 11
src/components/ZRichTexts/index.tsx

@@ -39,11 +39,12 @@ type Props = {
   isLook: boolean; //是否是查看进来
   ref: any; //当前自己的ref,给父组件调用
   myUrl: string; //上传的api地址
-  isOne?: boolean;
+  isOne?: boolean; //只显示单个富文本
+  upAudioBtnNone?: boolean; //是否能上传无障碍音频
 };
 
 function ZRichTexts(
-  { check, dirCode, isLook, myUrl, isOne = false }: Props,
+  { check, dirCode, isLook, myUrl, isOne = false, upAudioBtnNone = false }: Props,
   ref: any
 ) {
   const [sectionArr, setSectionArr] = useState<SectionArrType[]>([
@@ -304,14 +305,16 @@ function ZRichTexts(
           </Button>
         ) : (
           <div className="formRightZWRR">
-            <ZupAudio
-              fileInfo={sectionArr[0].fileInfo}
-              upDataFu={(info) => upSectionFu(info, 0)}
-              delFu={() => delSectionFu(0)}
-              dirCode={dirCode}
-              myUrl="cms/event/upload"
-              isLook={isLook}
-            />
+            {upAudioBtnNone ? null : (
+              <ZupAudio
+                fileInfo={sectionArr[0].fileInfo}
+                upDataFu={(info) => upSectionFu(info, 0)}
+                delFu={() => delSectionFu(0)}
+                dirCode={dirCode}
+                myUrl={myUrl}
+                isLook={isLook}
+              />
+            )}
 
             <div hidden={isLook} style={{ marginLeft: 20 }}>
               <Button
@@ -374,7 +377,7 @@ function ZRichTexts(
                   upDataFu={(info) => upSectionFu(info, index)}
                   delFu={() => delSectionFu(index)}
                   dirCode={dirCode}
-                  myUrl="cms/event/upload"
+                  myUrl={myUrl}
                   isLook={isLook}
                 />
                 &emsp;

+ 21 - 3
src/components/ZupTypes/index.module.scss

@@ -98,6 +98,21 @@
             cursor: move;
             position: relative;
 
+            // 第一张作为封面
+            .ZTbox1ImgRowCover {
+              font-size: 12px;
+              line-height: 22px;
+              position: absolute;
+              left: 0;
+              top: 0;
+              width: 100%;
+              height: 24px;
+              background-color: rgba(0, 0, 0, 0.8);
+              color: #fff;
+              text-align: center;
+              pointer-events: none;
+            }
+
             // 修改图片名字
             .ZTbox1ImgRowName {
               font-size: 12px;
@@ -176,14 +191,16 @@
 // 查看情况
 .ZupTypesLook {
   :global {
-    .ZTbox1ImgRowName{
+    .ZTbox1ImgRowName {
       cursor: default !important;
       color: #fff !important;
     }
-    .ZTbox1ImgRow{
+
+    .ZTbox1ImgRow {
       cursor: default !important;
     }
-    .ZTbox1ImgRowX{
+
+    .ZTbox1ImgRowX {
       display: none !important;
     }
   }
@@ -195,6 +212,7 @@
     .ant-modal-close {
       display: none;
     }
+
     .ZupTypesMoBtn {
       margin-top: 24px;
       text-align: center;

+ 23 - 7
src/components/ZupTypes/index.tsx

@@ -49,7 +49,8 @@ type Props = {
   videoTit?: string; //视频上传的提示语
   isTypeShow?: boolean; //默认就选中(只有一个类型的时候)
   isUpName?: boolean; //是否能修改图片名字
-  lastImgTxt?:string
+  lastImgTxt?: string; //加载最后面的上传提示
+  oneIsCover?: boolean; //是否将第一张作为封面
 };
 
 function ZupTypes(
@@ -67,7 +68,8 @@ function ZupTypes(
     videoTit = "",
     isTypeShow = false,
     isUpName = false,
-    lastImgTxt=''
+    lastImgTxt = "",
+    oneIsCover = false,
   }: Props,
   ref: any
 ) {
@@ -350,6 +352,7 @@ function ZupTypes(
 
   // --------------让父组件调用的返回 附件 信息
   const fileComFileResFu = useCallback(() => {
+    let coverUrl = "";
     const fileIds = [];
     if (fileList.model.id && typeCheck.includes("model"))
       fileIds.push(fileList.model.id);
@@ -358,14 +361,21 @@ function ZupTypes(
     if (fileList.video.id && typeCheck.includes("video"))
       fileIds.push(fileList.video.id);
     if (typeCheck.includes("img")) {
-      fileList.img.forEach((v) => {
-        if (v.id) fileIds.push(v.id);
+      fileList.img.forEach((v, i) => {
+        if (v.id) {
+          fileIds.push(v.id);
+          if (oneIsCover && i === 0) {
+            // 返回 第一张图的url 作为封面
+            coverUrl = v.filePath;
+          }
+        }
       });
     }
     return {
       sonType: typeCheck,
       sonFileIds: fileIds,
       sonIsOk: fileCheckFu,
+      coverUrl,
     };
   }, [
     fileCheckFu,
@@ -373,6 +383,7 @@ function ZupTypes(
     fileList.img,
     fileList.model.id,
     fileList.video.id,
+    oneIsCover,
     typeCheck,
   ]);
 
@@ -477,7 +488,7 @@ function ZupTypes(
             >
               <PlusOutlined rev={undefined} />
             </div>
-            {fileList.img.map((v) => (
+            {fileList.img.map((v, i) => (
               <div
                 className="ZTbox1ImgRow"
                 key={v.id}
@@ -496,6 +507,10 @@ function ZupTypes(
                   />
                 ) : null}
 
+                {oneIsCover && i === 0 ? (
+                  <div className="ZTbox1ImgRowCover">封面</div>
+                ) : null}
+
                 {/* 修改图片名字 */}
                 {isUpName ? (
                   <div
@@ -549,7 +564,8 @@ function ZupTypes(
               <br />
             </>
           ) : null}
-          支持png、jpg的图片格式;最大支持5M;最多支持{imgLength}张。{lastImgTxt}
+          支持png、jpg的图片格式;最大支持5M;最多支持{imgLength}张。
+          {lastImgTxt}
         </div>
       </div>
 
@@ -566,7 +582,7 @@ function ZupTypes(
           fileCheck && fileCheckFu ? "ZcheckTxtAc" : ""
         )}
       >
-        请最少上传一个展品!
+        请最少上传一张图片!
       </div>
 
       {/* 点击修改名字出来的弹窗 */}

+ 6 - 0
src/pages/A1event/A1add/index.module.scss

@@ -87,6 +87,12 @@
 
     // 从查看进入
     .A1eMainLook{
+
+      // 左边的 label 也不让选中
+      label{
+        pointer-events: none;
+      }
+
       .ant-picker{
         pointer-events: none;
       }

+ 4 - 2
src/pages/A1event/A1add/index.tsx

@@ -155,6 +155,7 @@ function A1add({ editInfo, closeFu, editTableFu, addTableFu }: Props) {
         dateEnd,
         fileName: nameAudio.fileName,
         filePath: nameAudio.filePath,
+        dirCode
       };
 
       const res = await A1_APIsave(obj);
@@ -166,6 +167,7 @@ function A1add({ editInfo, closeFu, editTableFu, addTableFu }: Props) {
       }
     },
     [
+      dirCode,
       addTableFu,
       closeFu,
       editInfo.id,
@@ -199,7 +201,7 @@ function A1add({ editInfo, closeFu, editTableFu, addTableFu }: Props) {
               label="标题"
               name="name"
               rules={[{ required: true, message: "请输入标题!" }]}
-              getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+              getValueFromEvent={(e) => e.target.value.trim()}
             >
               <Input
                 readOnly={editInfo.txt === "查看"}
@@ -325,7 +327,7 @@ function A1add({ editInfo, closeFu, editTableFu, addTableFu }: Props) {
           >
             <Select
               placeholder="请选择状态"
-              style={{ width: 200 }}
+              style={{ width: 149 }}
               options={[
                 { value: 1, label: "发布" },
                 { value: 0, label: "不发布" },

+ 1 - 1
src/pages/A1event/index.tsx

@@ -122,7 +122,7 @@ function A1event() {
               maxLength={50}
               showCount
               style={{ width: 300 }}
-              placeholder="请输入关键字,不超过50字"
+              placeholder="请输入关键字"
               allowClear
               onChange={(e) => fromKeyChangeFu(e, "searchKey")}
             />

+ 8 - 1
src/pages/A2exhibition/A2add/index.module.scss

@@ -103,6 +103,12 @@
 
     // 从查看进入
     .A2eMainLook {
+
+      // 左边的 label 也不让选中
+      label {
+        pointer-events: none;
+      }
+
       .ant-picker {
         pointer-events: none;
       }
@@ -118,7 +124,8 @@
       .ant-select {
         pointer-events: none;
       }
-      .ant-radio-wrapper{
+
+      .ant-radio-wrapper {
         pointer-events: none;
       }
     }

+ 12 - 6
src/pages/A2exhibition/A2add/index.tsx

@@ -187,7 +187,7 @@ function A2add({ editInfo, closeFu, editTableFu, addTableFu }: Props) {
 
       // 展品的校验
       const { sonFileIds: exhibitsFileIds } =
-        ZupFilesRef1.current?.fileComFileResFu() || [];
+        ZupFilesRef1.current?.fileComFileResFu();
 
       if (exhibitsFileIds.length <= 0) {
         return MessageFu.warning("请最少上传一个展品!");
@@ -195,7 +195,7 @@ function A2add({ editInfo, closeFu, editTableFu, addTableFu }: Props) {
 
       // 展馆的校验
       const { sonFileIds: exhibitionFileIds } =
-        ZupFilesRef2.current?.fileComFileResFu() || [];
+        ZupFilesRef2.current?.fileComFileResFu();
 
       if (exhibitionFileIds.length <= 0) {
         return MessageFu.warning("请最少上传一个展馆!");
@@ -289,7 +289,8 @@ function A2add({ editInfo, closeFu, editTableFu, addTableFu }: Props) {
               label="标题"
               name="name"
               rules={[{ required: true, message: "请输入标题!" }]}
-              getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+              // getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+              getValueFromEvent={(e) => e.target.value.trim()}
             >
               <Input
                 readOnly={editInfo.txt === "查看"}
@@ -358,10 +359,15 @@ function A2add({ editInfo, closeFu, editTableFu, addTableFu }: Props) {
             </div>
           </div>
 
-          {editInfo.txt === "查看"?<br/>:null}
+          {editInfo.txt === "查看" ? <br /> : null}
 
           <Form.Item label="摘要" name="digest">
-            <TextArea readOnly={editInfo.txt === "查看"} placeholder="请输入内容" maxLength={200} showCount />
+            <TextArea
+              readOnly={editInfo.txt === "查看"}
+              placeholder="请输入内容"
+              maxLength={200}
+              showCount
+            />
           </Form.Item>
 
           {/* 时间 */}
@@ -544,7 +550,7 @@ function A2add({ editInfo, closeFu, editTableFu, addTableFu }: Props) {
           >
             <Select
               placeholder="请选择状态"
-              style={{ width: 200 }}
+              style={{ width: 149 }}
               options={[
                 { value: 1, label: "发布" },
                 { value: 0, label: "不发布" },

+ 1 - 1
src/pages/A2exhibition/index.tsx

@@ -127,7 +127,7 @@ function A2exhibition() {
               maxLength={50}
               showCount
               style={{ width: 300 }}
-              placeholder="请输入关键字,不超过50字"
+              placeholder="请输入关键字"
               allowClear
               onChange={(e) => fromKeyChangeFu(e, "searchKey")}
             />

+ 8 - 1
src/pages/A3holding/A3add/index.module.scss

@@ -103,6 +103,12 @@
 
     // 从查看进入
     .A3eMainLook {
+
+      // 左边的 label 也不让选中
+      label {
+        pointer-events: none;
+      }
+
       .ant-picker {
         pointer-events: none;
       }
@@ -118,7 +124,8 @@
       .ant-select {
         pointer-events: none;
       }
-      .ant-radio-wrapper{
+
+      .ant-radio-wrapper {
         pointer-events: none;
       }
     }

+ 61 - 16
src/pages/A3holding/A3add/index.tsx

@@ -19,6 +19,7 @@ import ZRichTexts from "@/components/ZRichTexts";
 import ZupTypes from "@/components/ZupTypes";
 import MyPopconfirm from "@/components/MyPopconfirm";
 import TextArea from "antd/es/input/TextArea";
+import { A3Selct_1 } from "../data";
 
 type Props = {
   editInfo: A1EditInfoType;
@@ -59,10 +60,10 @@ function A3add({
 
       setDirCode(data.dirCode);
 
-      // 展示展馆
+      // 展示图片
       ZupFilesRef2.current?.setFileComFileFu({
         type: "img",
-        fileList: data.exhibitionFile || [],
+        fileList: data.files || [],
       });
 
       // 设置标题的 音频
@@ -96,31 +97,32 @@ function A3add({
   const onFinish = useCallback(
     async (values: any) => {
       setFileCheck(true);
-      // 发布日期
-      const datePublish = dayjs(values.myTime).format("YYYY-MM-DD");
+
+      // 图片的校验
+      const { sonFileIds: fileIds, coverUrl } =
+        ZupFilesRef2.current?.fileComFileResFu();
+
+      if (fileIds.length <= 0) {
+        return MessageFu.warning("请最少上传一张图片!");
+      }
 
       // 富文本校验不通过
       const rtf = ZRichTextRef.current?.fatherBtnOkFu() || { flag: true };
 
       if (rtf.flag) return MessageFu.warning("请输入完整正文!");
 
-      // 展馆的校验
-      const { sonFileIds: exhibitionFileIds } =
-        ZupFilesRef2.current?.fileComFileResFu() || [];
-
-      if (exhibitionFileIds.length <= 0) {
-        return MessageFu.warning("请最少上传一张图片!");
-      }
+      // 发布日期
+      const datePublish = dayjs(values.myTime).format("YYYY-MM-DD");
 
       const obj = {
         ...values,
         id: editInfo.id > 0 ? editInfo.id : null,
         datePublish,
-        // thumb: coverUrl1.filePath, //待完善
+        thumb: coverUrl,
         rtf: JSON.stringify(rtf.val || ""),
         fileName: nameAudio.fileName,
         filePath: nameAudio.filePath,
-        exhibitionFileIds: exhibitionFileIds.join(","),
+        fileIds: fileIds.join(","),
         dirCode,
       };
       const res = await A3_APIsave(obj);
@@ -169,7 +171,7 @@ function A3add({
               label="名称"
               name="name"
               rules={[{ required: true, message: "请输入名称!" }]}
-              getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+              // getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
             >
               <Input
                 readOnly={editInfo.txt === "查看"}
@@ -208,11 +210,54 @@ function A3add({
                 isLook={editInfo.txt === "查看"}
                 imgLength={50}
                 isTypeShow={true}
-                lastImgTxt='第一张将作为封面'
+                lastImgTxt="第一张将作为封面"
+                oneIsCover={true}
               />
             </div>
           </div>
 
+          <Form.Item
+            label="类别"
+            name="type"
+            rules={[{ required: true, message: "请选择类别!" }]}
+          >
+            <Select
+              placeholder="请选择类别"
+              style={{ width: 200 }}
+              options={A3Selct_1.filter((v) => v.label !== "全部")}
+            />
+          </Form.Item>
+
+          <Form.Item
+            label="年代"
+            name="dictAgeId"
+            rules={[{ required: true, message: "请选择年代!" }]}
+          >
+            <Select
+              placeholder="请选择年代"
+              style={{ width: 200 }}
+              options={selectAgeArr.filter((v) => v.label !== "全部")}
+            />
+          </Form.Item>
+
+          <Form.Item label="作者" name="author">
+            <Input
+              readOnly={editInfo.txt === "查看"}
+              maxLength={50}
+              showCount
+              placeholder="请输入内容"
+            />
+          </Form.Item>
+
+          <Form.Item label="尺寸" name="size">
+            <Input
+              readOnly={editInfo.txt === "查看"}
+              maxLength={50}
+              showCount
+              placeholder="请输入内容"
+            />
+          </Form.Item>
+
           <Form.Item label="摘要" name="digest">
             <TextArea
               readOnly={editInfo.txt === "查看"}
@@ -273,7 +318,7 @@ function A3add({
           >
             <Select
               placeholder="请选择状态"
-              style={{ width: 200 }}
+              style={{ width: 149 }}
               options={[
                 { value: 1, label: "发布" },
                 { value: 0, label: "不发布" },

+ 1 - 1
src/pages/A3holding/index.tsx

@@ -142,7 +142,7 @@ function A3holding() {
               maxLength={50}
               showCount
               style={{ width: 300 }}
-              placeholder="请输入关键字,不超过50字"
+              placeholder="请输入关键字"
               allowClear
               onChange={(e) => fromKeyChangeFu(e, "searchKey")}
             />

+ 133 - 0
src/pages/A4study/A4add/index.module.scss

@@ -0,0 +1,133 @@
+.A4add {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 12;
+  background-color: #fff;
+  border-radius: 10px;
+  padding: 24px;
+
+  :global {
+    .A4eMain {
+      width: 100%;
+      height: 100%;
+      overflow-y: auto;
+
+
+      .A4fromRow {
+        position: relative;
+        width: 800px;
+        height: 56px;
+
+        // &>div {
+        //   width: 100%;
+        // }
+
+        .A4_1Frow {
+          position: absolute;
+          top: 0px;
+          left: 600px;
+          width: 200px;
+        }
+
+        .A4_4Frow {
+          position: absolute;
+          left: 400px;
+          top: 4px;
+        }
+
+        .A4_6Frow {
+          position: absolute;
+          left: 200px;
+          top: 5px;
+          color: #999;
+          font-size: 12px;
+        }
+
+      }
+
+      .ant-form {
+        width: 800px;
+
+        // .ant-input-affix-wrapper{
+        //   width: 800px;
+        // }
+        .formRow {
+          display: flex;
+
+          .formLeft {
+            position: relative;
+            top: 3px;
+            width: 100px;
+            text-align: right;
+
+            &>span {
+              color: #ff4d4f;
+            }
+          }
+
+          .formRight {
+            width: calc(100% - 100px);
+          }
+
+
+          .formRight5Tit {
+            position: relative;
+            top: -10px;
+            transition: top .2s;
+            margin: 5px 0;
+            color: #ff4d4f;
+            opacity: 0;
+            pointer-events: none;
+          }
+
+          .formRight5TitErr {
+            opacity: 1;
+            top: 0;
+          }
+        }
+
+
+        .A4Ebtn {
+          position: absolute;
+          z-index: 10;
+          left: 1200px;
+          top: 50%;
+          transform: translateY(-50%);
+        }
+      }
+    }
+
+
+    // 从查看进入
+    .A4eMainLook {
+
+      // 左边的 label 也不让选中
+      label {
+        pointer-events: none;
+      }
+
+      .ant-picker {
+        pointer-events: none;
+      }
+
+      .ant-checkbox-wrapper {
+        pointer-events: none;
+      }
+
+      .ant-input-number {
+        pointer-events: none;
+      }
+
+      .ant-select {
+        pointer-events: none;
+      }
+
+      .ant-radio-wrapper {
+        pointer-events: none;
+      }
+    }
+  }
+}

+ 347 - 0
src/pages/A4study/A4add/index.tsx

@@ -0,0 +1,347 @@
+import React, { useCallback, useEffect, useRef, useState } from "react";
+import styles from "./index.module.scss";
+import { A1EditInfoType } from "@/pages/A1event/data";
+import {
+  Button,
+  DatePicker,
+  Form,
+  FormInstance,
+  Input,
+  InputNumber,
+  Select,
+} from "antd";
+import dayjs from "dayjs";
+import { MessageFu } from "@/utils/message";
+import classNames from "classnames";
+import ZupOne from "@/components/ZupOne";
+import TextArea from "antd/es/input/TextArea";
+import ZRichTexts from "@/components/ZRichTexts";
+import MyPopconfirm from "@/components/MyPopconfirm";
+import { A4Selct_1 } from "../data";
+import { A4_APIgetInfo, A4_APIsave } from "@/store/action/A4study";
+
+type Props = {
+  editInfo: A1EditInfoType;
+  closeFu: () => void;
+  editTableFu: () => void;
+  addTableFu: () => void;
+};
+
+function A4add({ editInfo, closeFu, editTableFu, addTableFu }: Props) {
+  const [dirCode, setDirCode] = useState("");
+
+  // 表单的ref
+  const FormBoxRef = useRef<FormInstance>(null);
+
+  // 封面图的ref
+  const ZupThumbRef = useRef<any>(null);
+
+  // 富文本的ref
+  const ZRichTextRef = useRef<any>(null);
+
+  // 编辑/查看 进入页面 获取信息
+  const getInfoFu = useCallback(async (id: number) => {
+    const res = await A4_APIgetInfo(id);
+    if (res.code === 0) {
+      const data = res.data;
+
+      setDirCode(data.dirCode);
+
+      // 设置富文本
+      ZRichTextRef.current?.ritxtShowFu(JSON.parse(data.rtf));
+
+      const obj = {
+        ...data,
+        myTime: dayjs(data.datePublish),
+        myTimeSta: dayjs(data.dateStart),
+      };
+
+      if (data.dateEnd) {
+        obj.myTimeEnd = dayjs(data.dateEnd);
+      }
+
+      FormBoxRef.current?.setFieldsValue(obj);
+
+      // 设置封面图
+      ZupThumbRef.current?.setFileComFileFu({
+        fileName: "",
+        filePath: data.thumb,
+      });
+    }
+  }, []);
+
+  // 附件 是否 已经点击过确定
+  const [fileCheck, setFileCheck] = useState(false);
+
+  // 没有通过校验
+  const onFinishFailed = useCallback(() => {
+    setFileCheck(true);
+  }, []);
+
+  //  通过校验点击确定
+  const onFinish = useCallback(
+    async (values: any) => {
+      setFileCheck(true);
+
+      const coverUrl1 = ZupThumbRef.current?.fileComFileResFu();
+      // 没有传 封面图
+      if (!coverUrl1.filePath) return MessageFu.warning("请上传封面图!");
+
+      // 发布日期
+      const datePublish = dayjs(values.myTime).format("YYYY-MM-DD");
+
+      // 开始时间
+      const dateStart = dayjs(values.myTimeSta).format("YYYY-MM-DD HH:mm");
+
+      // 结束时间(可能为空)
+      let dateEnd = "";
+      if (values.myTimeEnd)
+        dateEnd = dayjs(values.myTimeEnd).format("YYYY-MM-DD HH:mm");
+
+      // 富文本校验不通过
+      const rtf = ZRichTextRef.current?.fatherBtnOkFu() || { flag: true };
+
+      if (rtf.flag) return MessageFu.warning("请输入完整正文!");
+
+      const obj = {
+        ...values,
+        id: editInfo.id > 0 ? editInfo.id : null,
+        datePublish,
+        thumb: coverUrl1.filePath,
+        rtf: JSON.stringify(rtf.val || ""),
+        dirCode,
+        dateStart,
+        dateEnd,
+      };
+
+      // if (obj) {
+      //   console.log(123, obj);
+      //   return;
+      // }
+
+      const res = await A4_APIsave(obj);
+
+      if (res.code === 0) {
+        MessageFu.success(`${editInfo.txt}成功!`);
+        editInfo.id > 0 ? editTableFu() : addTableFu();
+        closeFu();
+      }
+    },
+    [addTableFu, closeFu, dirCode, editInfo.id, editInfo.txt, editTableFu]
+  );
+
+  useEffect(() => {
+    if (editInfo.id > 0) {
+      getInfoFu(editInfo.id);
+    } else {
+      setDirCode(Date.now() + "");
+      FormBoxRef.current?.setFieldsValue({
+        myTime: dayjs(Date.now()),
+        sort: 999,
+        display: 1,
+      });
+    }
+  }, [editInfo.id, getInfoFu]);
+
+  return (
+    <div className={styles.A4add}>
+      <div
+        className={classNames(
+          "A4eMain",
+          editInfo.txt === "查看" ? "A4eMainLook" : ""
+        )}
+      >
+        <Form
+          ref={FormBoxRef}
+          name="basic"
+          labelCol={{ span: 3 }}
+          onFinish={onFinish}
+          onFinishFailed={onFinishFailed}
+          autoComplete="off"
+          scrollToFirstError
+        >
+          <Form.Item
+            label="标题"
+            name="name"
+            rules={[{ required: true, message: "请输入标题!" }]}
+            // getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+            getValueFromEvent={(e) => e.target.value.trim()}
+          >
+            <Input
+              readOnly={editInfo.txt === "查看"}
+              style={{ width: "500px" }}
+              maxLength={50}
+              showCount
+              placeholder="请输入内容"
+            />
+          </Form.Item>
+
+          <Form.Item
+            label="板块"
+            name="type"
+            rules={[{ required: true, message: "请选择板块!" }]}
+          >
+            <Select
+              placeholder="请选择板块"
+              style={{ width: 200 }}
+              options={A4Selct_1.filter((v) => v.label !== "全部")}
+            />
+          </Form.Item>
+
+          <Form.Item
+            label="开始时间"
+            name="myTimeSta"
+            rules={[{ required: true, message: "请选择开始时间!" }]}
+          >
+            <DatePicker
+              showTime
+              format={"YYYY-MM-DD HH:mm"}
+              placeholder="请选择开始时间"
+            />
+          </Form.Item>
+
+          <Form.Item label="结束时间" name="myTimeEnd">
+            <DatePicker
+              showTime
+              format={"YYYY-MM-DD HH:mm"}
+              placeholder="请选择结束时间"
+            />
+          </Form.Item>
+
+          <Form.Item
+            label="地点"
+            name="address"
+            rules={[{ required: true, message: "请输入标题!" }]}
+            getValueFromEvent={(e) => e.target.value.trim()}
+          >
+            <TextArea
+              readOnly={editInfo.txt === "查看"}
+              placeholder="请输入内容"
+              maxLength={100}
+              showCount
+            />
+          </Form.Item>
+
+          <Form.Item
+            label="人数限制"
+            name="remark"
+            rules={[{ required: true, message: "请输入标题!" }]}
+            getValueFromEvent={(e) => e.target.value.trim()}
+          >
+            <TextArea
+              readOnly={editInfo.txt === "查看"}
+              placeholder="请输入内容"
+              maxLength={100}
+              showCount
+            />
+          </Form.Item>
+
+          {/* 封面 */}
+          <div className="formRow">
+            <div className="formLeft">
+              <span>* </span>
+              封面:
+            </div>
+            <div className="formRight">
+              <ZupOne
+                ref={ZupThumbRef}
+                isLook={editInfo.txt === "查看"}
+                fileCheck={fileCheck}
+                size={5}
+                dirCode={dirCode}
+                myUrl="cms/learn/upload"
+                format={["image/jpeg", "image/png"]}
+                formatTxt="png、jpg和jpeg"
+                checkTxt="请上传封面图!"
+                upTxt="最多1张"
+                myType="thumb"
+              />
+            </div>
+          </div>
+
+          {editInfo.txt === "查看" ? <br /> : null}
+
+          {/* 正文 */}
+          <div className="formRow">
+            <div className="formLeft">
+              <span>* </span>
+              正文:
+            </div>
+            <div className="formRight">
+              <ZRichTexts
+                check={fileCheck}
+                dirCode={dirCode}
+                isLook={editInfo.txt === "查看"}
+                ref={ZRichTextRef}
+                myUrl="cms/learn/upload"
+                isOne={true}
+                upAudioBtnNone={true}
+              />
+            </div>
+          </div>
+
+          <Form.Item
+            label="发布日期"
+            name="myTime"
+            rules={[{ required: true, message: "请选择发布日期!" }]}
+          >
+            <DatePicker />
+          </Form.Item>
+
+          <div className="A4fromRow">
+            <Form.Item
+              label="排序值"
+              name="sort"
+              rules={[{ required: true, message: "请输入排序值!" }]}
+            >
+              <InputNumber
+                min={1}
+                max={999}
+                precision={0}
+                placeholder="请输入"
+              />
+            </Form.Item>
+            <div className="A4_6Frow" hidden={editInfo.txt === "查看"}>
+              请输入1~999的数字。数字越小,排序越靠前。数字相同时,更新发布的内容排在前面
+            </div>
+          </div>
+
+          <Form.Item
+            label="状态"
+            name="display"
+            rules={[{ required: true, message: "请选择状态!" }]}
+          >
+            <Select
+              placeholder="请选择状态"
+              style={{ width: 149 }}
+              options={[
+                { value: 1, label: "发布" },
+                { value: 0, label: "不发布" },
+              ]}
+            />
+          </Form.Item>
+
+          {/* 确定和取消按钮 */}
+          <Form.Item className="A4Ebtn">
+            {editInfo.txt === "查看" ? (
+              <Button onClick={closeFu}>返回</Button>
+            ) : (
+              <>
+                <Button type="primary" htmlType="submit">
+                  提交
+                </Button>
+                <br />
+                <br />
+                <MyPopconfirm txtK="取消" onConfirm={closeFu} />
+              </>
+            )}
+          </Form.Item>
+        </Form>
+      </div>
+    </div>
+  );
+}
+
+const MemoA4add = React.memo(A4add);
+
+export default MemoA4add;

+ 14 - 0
src/pages/A4study/data.ts

@@ -0,0 +1,14 @@
+export type A4FromDataType= {
+  pageNum: number;
+  pageSize: number;
+  searchKey: string;
+  type:string
+  display: ''|0|1;
+}
+
+export const A4Selct_1 = [
+  { value: "", label: "全部" },
+  { value: "For Students", label: "For Students" },
+  { value: "For Adults", label: "For Adults" },
+  { value: "For Families & Children", label: "For Families & Children" },
+];

+ 27 - 3
src/pages/A4study/index.module.scss

@@ -1,5 +1,29 @@
-.A4study{
-  :global{
-    
+.A4study {
+  position: relative;
+
+  :global {
+    .A4top {
+      padding: 15px 24px;
+      border-radius: 10px;
+      background-color: #fff;
+      display: flex;
+      justify-content: space-between;
+
+      .A4topLeft {
+        display: flex;
+
+        &>div {
+          margin-right: 24px;
+        }
+      }
+    }
+
+    .A4tableBox {
+      border-radius: 10px;
+      overflow: hidden;
+      margin-top: 15px;
+      height: calc(100% - 77px);
+      background-color: #fff;
+    }
   }
 }

+ 193 - 5
src/pages/A4study/index.tsx

@@ -1,12 +1,200 @@
-import React from "react";
+import React, {
+  useCallback,
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+} from "react";
 import styles from "./index.module.scss";
- function A4study() {
-  
+import { useDispatch, useSelector } from "react-redux";
+import { A4FromDataType, A4Selct_1 } from "./data";
+import { A4_APIdel, A4_APIgetList } from "@/store/action/A4study";
+import { RootState } from "@/store";
+import { MessageFu } from "@/utils/message";
+import { A4tableType } from "@/types";
+import { Button, Input, Select } from "antd";
+import MyPopconfirm from "@/components/MyPopconfirm";
+import { A1EditInfoType, A1Selct } from "../A1event/data";
+import MyTable from "@/components/MyTable";
+import { A4tableC } from "@/utils/tableData";
+import A4add from "./A4add";
+function A4study() {
+  const dispatch = useDispatch();
+
+  const [fromData, setFromData] = useState<A4FromDataType>({
+    pageNum: 1,
+    pageSize: 10,
+    searchKey: "",
+    type: "",
+    display: "",
+  });
+  const getListFu = useCallback(() => {
+    dispatch(A4_APIgetList(fromData));
+  }, [dispatch, fromData]);
+
+  useEffect(() => {
+    getListFu();
+  }, [getListFu]);
+
+  const [inputKey, setInputKey] = useState(1);
+
+  // 标题的输入
+  const timeRef = useRef(-1);
+  const fromKeyChangeFu = useCallback(
+    (e: React.ChangeEvent<HTMLInputElement>, key: "searchKey") => {
+      clearTimeout(timeRef.current);
+      timeRef.current = window.setTimeout(() => {
+        setFromData({ ...fromData, [key]: e.target.value, pageNum: 1 });
+      }, 500);
+    },
+    [fromData]
+  );
+
+  // 点击重置
+  const resetSelectFu = useCallback(() => {
+    setInputKey(Date.now());
+    setFromData({
+      pageNum: 1,
+      pageSize: 10,
+      searchKey: "",
+      type: "",
+      display: "",
+    });
+  }, []);
+
+  const tableInfo = useSelector((state: RootState) => state.A4study.tableInfo);
+
+  const delTableFu = useCallback(
+    async (id: number) => {
+      const res = await A4_APIdel(id);
+      if (res.code === 0) {
+        MessageFu.success("删除成功!");
+        getListFu();
+      }
+    },
+    [getListFu]
+  );
+
+  const tableLastBtn = useMemo(() => {
+    return [
+      {
+        title: "操作",
+        render: (item: A4tableType) => (
+          <>
+            <Button
+              size="small"
+              type="text"
+              onClick={() => setEditInfo({ id: item.id, txt: "查看" })}
+            >
+              查看
+            </Button>
+            <Button
+              size="small"
+              type="text"
+              onClick={() => setEditInfo({ id: item.id, txt: "编辑" })}
+            >
+              编辑
+            </Button>
+            <MyPopconfirm txtK="删除" onConfirm={() => delTableFu(item.id)} />
+          </>
+        ),
+      },
+    ];
+  }, [delTableFu]);
+
+  //查看、新增、编辑
+  const [editInfo, setEditInfo] = useState<A1EditInfoType>({
+    id: 0,
+    txt: "",
+  });
+
   return (
     <div className={styles.A4study}>
-       <div className="pageTitle">学习参与管理</div>
+      <div className="pageTitle">
+        学习参与管理{editInfo.id ? ` - ${editInfo.txt}` : ""}
+      </div>
+      {/* 顶部筛选 */}
+      <div className="A4top">
+        <div className="A4topLeft">
+          <div>
+            <span>名称:</span>
+            <Input
+              key={inputKey}
+              maxLength={50}
+              showCount
+              style={{ width: 300 }}
+              placeholder="请输入关键字"
+              allowClear
+              onChange={(e) => fromKeyChangeFu(e, "searchKey")}
+            />
+          </div>
+
+          <div>
+            <span>板块:</span>
+            <Select
+              placeholder="请选择"
+              style={{ width: 200 }}
+              value={fromData.type}
+              onChange={(e) =>
+                setFromData({ ...fromData, pageNum: 1, type: e })
+              }
+              options={A4Selct_1}
+            />
+          </div>
+
+          <div>
+            <span>状态:</span>
+            <Select
+              placeholder="请选择"
+              style={{ width: 100 }}
+              value={fromData.display}
+              onChange={(e) =>
+                setFromData({ ...fromData, pageNum: 1, display: e })
+              }
+              options={A1Selct}
+            />
+          </div>
+        </div>
+
+        <div>
+          <Button
+            type="primary"
+            onClick={() => setEditInfo({ id: -1, txt: "新增" })}
+          >
+            新增
+          </Button>
+          &emsp;
+          <Button onClick={resetSelectFu}>重置</Button>
+        </div>
+      </div>
+
+      {/* 表格主体 */}
+      <div className="A4tableBox">
+        <MyTable
+          yHeight={625}
+          list={tableInfo.list}
+          columnsTemp={A4tableC}
+          lastBtn={tableLastBtn}
+          pageNum={fromData.pageNum}
+          pageSize={fromData.pageSize}
+          total={tableInfo.total}
+          onChange={(pageNum, pageSize) =>
+            setFromData({ ...fromData, pageNum, pageSize })
+          }
+        />
+      </div>
+
+      {/* 新增 编辑 查看 */}
+      {editInfo.id ? (
+        <A4add
+          editInfo={editInfo}
+          closeFu={() => setEditInfo({ id: 0, txt: "" })}
+          editTableFu={() => getListFu()}
+          addTableFu={() => resetSelectFu()}
+        />
+      ) : null}
     </div>
-  )
+  );
 }
 
 const MemoA4study = React.memo(A4study);

+ 41 - 0
src/store/action/A4study.ts

@@ -0,0 +1,41 @@
+import http from "@/utils/http";
+import { AppDispatch } from "..";
+
+/**
+ *学习参与管理-列表
+ */
+
+export const A4_APIgetList = (data: any): any => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post("cms/learn/pageList", data);
+    if (res.code === 0) {
+      const obj = {
+        // 待完善
+        list: res.data.records,
+        total: res.data.total,
+      };
+      dispatch({ type: "A4/getList", payload: obj });
+    }
+  };
+};
+
+/**
+ * 学习参与管理-删除
+ */
+export const A4_APIdel = (id: number) => {
+  return http.get(`cms/learn/removes/${id}`);
+};
+
+/**
+ * 学习参与管理-获取详情
+ */
+export const A4_APIgetInfo = (id: number) => {
+  return http.get(`cms/learn/detail/${id}`);
+};
+
+/**
+ * 学习参与管理-新增、编辑
+ */
+export const A4_APIsave = (data: any) => {
+  return http.post("cms/learn/save", data);
+};

+ 28 - 0
src/store/reducer/A4study.ts

@@ -0,0 +1,28 @@
+import { A4tableType } from "@/types";
+
+// 初始化状态
+const initState = {
+  // 列表数据
+  tableInfo: {
+    list: [] as A4tableType[],
+    total: 0,
+  },
+};
+
+// 定义 action 类型
+type Props = {
+  type: "A4/getList";
+  payload: { list: A4tableType[]; total: number };
+};
+
+// reducer
+export default function Reducer(state = initState, action: Props) {
+  switch (action.type) {
+    // 获取列表数据
+    case "A4/getList":
+      return { ...state, tableInfo: action.payload };
+
+    default:
+      return state;
+  }
+}

+ 2 - 0
src/store/reducer/index.ts

@@ -6,6 +6,7 @@ import A0Layout from "./layout";
 import A1event from "./A1event";
 import A2exhibition from "./A2exhibition";
 import A3holding from "./A3holding";
+import A4study from "./A4study";
 import A8dict from "./A8dict";
 import Z1user from "./Z1user";
 import Z2log from "./Z2log";
@@ -16,6 +17,7 @@ const rootReducer = combineReducers({
   A1event,
   A2exhibition,
   A3holding,
+  A4study,
   A8dict,
   Z1user,
   Z2log,

+ 19 - 0
src/types/api/A4study.d.ts

@@ -0,0 +1,19 @@
+export type A4tableType = {
+	address: string;
+	createTime: string;
+	// creatorId?: any;
+	creatorName: string;
+	// dateEnd?: any;
+	// datePublish?: any;
+	// dateStart?: any;
+	dirCode: string;
+	display: number;
+	id: number;
+	name: string;
+	remark: string;
+	rtf: string;
+	sort: number;
+	thumb: string;
+	type: string;
+	updateTime: string;
+}

+ 1 - 0
src/types/index.d.ts

@@ -2,6 +2,7 @@ export * from './api/layot'
 export * from './api/A1event'
 export * from './api/A2exhibition'
 export * from './api/A3holding'
+export * from './api/A4study'
 export * from './api/A8dict'
 export * from './api/Z1user'
 export * from './api/Z2log'

+ 11 - 0
src/utils/tableData.ts

@@ -48,6 +48,17 @@ export const A3tableC = [
   ["txtChange", "状态", "display", { 0: "不发布", 1: "发布" }],
 ];
 
+export const A4tableC = [
+  ["txt", "标题", "name"],
+  ["txt", "板块", "type"],
+  ["img", "封面", "thumb"],
+  ["text", "地点", "address", 50],
+  ["txt", "最近编辑日期", "updateTime"],
+  ["txt", "编辑人", "creatorName"],
+  ["txt", "排序值", "sort"],
+  ["txtChange", "状态", "display", { 0: "不发布", 1: "发布" }],
+];
+
 export const A8tableC = [
   ["txt", "字典值", "name"],
   ["txt", "最近编辑日期", "updateTime"],