shaogen1995 2 lat temu
rodzic
commit
28c5cdd054

+ 18 - 0
houtai/src/assets/styles/base.css

@@ -163,3 +163,21 @@ textarea {
   height: 20px;
   background-color: var(--themeColor);
 }
+.mySorrl::-webkit-scrollbar {
+  /*滚动条整体样式*/
+  width: 5px;
+  /*高宽分别对应横竖滚动条的尺寸*/
+  height: 1px;
+}
+.mySorrl::-webkit-scrollbar-thumb {
+  /*滚动条里面小方块*/
+  border-radius: 10px;
+  -webkit-box-shadow: inset 0 0 5px transparent;
+  background: var(--themeColor);
+}
+.mySorrl::-webkit-scrollbar-track {
+  /*滚动条里面轨道*/
+  -webkit-box-shadow: inset 0 0 5px transparent;
+  border-radius: 10px;
+  background: transparent;
+}

+ 23 - 0
houtai/src/assets/styles/base.less

@@ -196,6 +196,7 @@ textarea {
   display: none;
 }
 
+// 页面标题
 .pageTitle{
   font-size: 20px;
   font-weight: 700;
@@ -215,4 +216,26 @@ textarea {
     height: 20px;
     background-color: var(--themeColor);
   }
+}
+
+// 滚动条
+.mySorrl::-webkit-scrollbar {
+  /*滚动条整体样式*/
+  width: 5px;
+  /*高宽分别对应横竖滚动条的尺寸*/
+  height: 1px;
+}
+
+.mySorrl::-webkit-scrollbar-thumb {
+  /*滚动条里面小方块*/
+  border-radius: 10px;
+  -webkit-box-shadow: inset 0 0 5px transparent;
+  background: var(--themeColor);
+}
+
+.mySorrl::-webkit-scrollbar-track {
+  /*滚动条里面轨道*/
+  -webkit-box-shadow: inset 0 0 5px transparent;
+  border-radius: 10px;
+  background: transparent;
 }

+ 0 - 20
houtai/src/pages/A1Hot/index.module.scss

@@ -91,26 +91,6 @@
           }
         }
 
-        .hotListBox::-webkit-scrollbar {
-          /*滚动条整体样式*/
-          width: 5px;
-          /*高宽分别对应横竖滚动条的尺寸*/
-          height: 1px;
-        }
-
-        .hotListBox::-webkit-scrollbar-thumb {
-          /*滚动条里面小方块*/
-          border-radius: 10px;
-          -webkit-box-shadow: inset 0 0 5px transparent;
-          background: var(--themeColor);
-        }
-
-        .hotListBox::-webkit-scrollbar-track {
-          /*滚动条里面轨道*/
-          -webkit-box-shadow: inset 0 0 5px transparent;
-          border-radius: 10px;
-          background: transparent;
-        }
 
         .hotListBox {
           width: 100%;

+ 1 - 1
houtai/src/pages/A1Hot/index.tsx

@@ -335,7 +335,7 @@ function Hot() {
               </div>
             </div>
             {/* 馆藏数据 */}
-            <div className="hotListBox" id="goodsSroolBox">
+            <div className="hotListBox mySorrl" id="goodsSroolBox">
               {list2.length ? (
                 list2.slice(0, 20).map((v) => (
                   <div className="row" key={v.id}>

+ 2 - 22
houtai/src/pages/A2News/NewsAdd/index.module.scss

@@ -10,10 +10,10 @@
 
   :global {
     .formBox {
-      width: 900px;
+      width: 1200px;
       margin-top: 15px;
       height: calc(100% - 75px);
-      padding-right: 100px;
+      padding-right: 400px;
       overflow-y: auto;
 
 
@@ -177,25 +177,5 @@
       opacity: 1;
     }
 
-    .formBox::-webkit-scrollbar {
-      /*滚动条整体样式*/
-      width: 5px;
-      /*高宽分别对应横竖滚动条的尺寸*/
-      height: 1px;
-    }
-
-    .formBox::-webkit-scrollbar-thumb {
-      /*滚动条里面小方块*/
-      border-radius: 10px;
-      -webkit-box-shadow: inset 0 0 5px transparent;
-      background: var(--themeColor);
-    }
-
-    .formBox::-webkit-scrollbar-track {
-      /*滚动条里面轨道*/
-      -webkit-box-shadow: inset 0 0 5px transparent;
-      border-radius: 10px;
-      background: transparent;
-    }
   }
 }

+ 17 - 3
houtai/src/pages/A2News/NewsAdd/index.tsx

@@ -198,7 +198,7 @@ function NewsAdd({
         fileIds:
           tableType === "news"
             ? imgList.map((v) => v.id).join(",")
-            : fileOne.id,
+            : fileOne.id + "",
       };
       console.log(obj);
       if (id > 0) editTableFu();
@@ -221,7 +221,7 @@ function NewsAdd({
   return (
     <div className={styles.NewsAdd}>
       <div className="pageTitle">{id > 0 ? "编辑资讯" : "新增资讯"}</div>
-      <div className="formBox">
+      <div className="formBox mySorrl">
         <Form
           ref={FormBoxRef}
           name="basic"
@@ -259,7 +259,21 @@ function NewsAdd({
               <Form.Item
                 label="正文"
                 name="myTxt"
-                rules={[{ required: true, message: "请输入正文!" }]}
+                rules={[
+                  { required: true, message: "请输入正文!" },
+                  {
+                    validator: (rule, value) => {
+                      if (value) {
+                        const txt = value
+                          .replaceAll(" ", "")
+                          .replaceAll("\n", "");
+                        return txt === ""
+                          ? Promise.reject("请输入有效字符!")
+                          : Promise.resolve();
+                      } else return Promise.resolve();
+                    },
+                  },
+                ]}
                 // getValueFromEvent={(e) => e.target.value.trim()}
               >
                 <TextArea

+ 198 - 0
houtai/src/pages/A3Goods/GoodsAdd/index.module.scss

@@ -0,0 +1,198 @@
+.GoodsAdd {
+  position: absolute;
+  z-index: 20;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+
+  border-radius: 10px;
+  background-color: #fff;
+
+  :global {
+    .main {
+      margin-top: 5px;
+      width: 1200px;
+      padding-right: 400px;
+      padding-left:15px;
+      height: calc(100% - 66px);
+      overflow-y: auto;
+      overflow-y: overlay;
+      .myformBox0 {
+        margin-top: 0px;
+      }
+
+      .myformBox {
+        .ant-btn-default {
+          width: 100px;
+        }
+
+        display: flex;
+        margin-bottom: 20px;
+
+        .label {
+          width: 100px;
+          text-align: right;
+
+          &>span {
+            position: relative;
+            top: 2px;
+            color: #ff4d4f;
+          }
+        }
+
+      }
+
+      .myformBox2 {
+        align-items: center;
+        height: 32px;
+
+        .label {
+          height: 32px;
+          line-height: 32px;
+        }
+
+        .fileTit {
+          margin-left: 20px;
+          font-size: 14px;
+          color: rgb(126, 124, 124);
+        }
+
+        .fileInfo {
+          height: 32px;
+          line-height: 32px;
+          display: flex;
+          font-size: 16px;
+
+          .clearCover {
+            margin-left: 20px;
+            cursor: pointer;
+            font-size: 18px;
+          }
+
+        }
+
+
+      }
+
+      .myformBox3 {
+        margin-top: 20px;
+
+        .upImgBox {
+          display: flex;
+          flex-wrap: wrap;
+
+          &>div {
+            margin: 0 15px 15px 0;
+          }
+
+          .fileBoxRow_r_img {
+            position: relative;
+
+
+            .clearCover {
+              right: -10px;
+              top: -10px;
+              transform: translate(0, 0);
+              background-color: rgba(0, 0, 0, .8);
+              width: 20px;
+              height: 20px;
+              border-radius: 50%;
+              font-size: 16px;
+              color: #fff;
+            }
+          }
+        }
+
+        .fileTit {
+          font-size: 14px;
+          color: rgb(126, 124, 124);
+        }
+      }
+
+      .fileBoxRow_r {
+        position: relative;
+
+        .fileBoxRow_up {
+          color: #a6a6a6;
+          border-radius: 3px;
+          cursor: pointer;
+          font-size: 30px;
+          width: 100px;
+          height: 100px;
+          border: 1px dashed #797979;
+          display: flex;
+          justify-content: center;
+          align-items: center;
+
+
+        }
+
+        .fileBoxRow_r_img {
+          width: 100px;
+          height: 100px;
+          position: relative;
+
+          .clearCover {
+            cursor: pointer;
+            z-index: 10;
+            position: absolute;
+            width: 50px;
+            height: 50px;
+            top: 50%;
+            transform: translateY(-50%);
+            right: -50px;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            font-size: 24px;
+          }
+        }
+
+        .fileBoxRow_r_tit {
+          height: 46px;
+          margin-top: 5px;
+          font-size: 14px;
+          color: rgb(126, 124, 124);
+
+
+        }
+      }
+
+      .noUpThumb {
+        position: relative;
+        overflow: hidden;
+        opacity: 0;
+        transition: top .2s;
+        color: #ff4d4f;
+        top: -10px;
+      }
+
+      .noUpThumb2 {
+        margin-top: -10px;
+        position: relative;
+        padding-left: 100px;
+        margin-bottom: 12px;
+      }
+
+      .noUpThumbAc {
+        top: 0;
+        opacity: 1;
+      }
+
+      .myformBox {
+        .laseFormRight {
+          .laseFormRightRow {
+            display: flex;
+            align-items: center;
+          }
+
+          .laseFormRightTit {
+            font-size: 14px;
+            color: rgb(126, 124, 124);
+          }
+        }
+      }
+    }
+  }
+}

+ 737 - 0
houtai/src/pages/A3Goods/GoodsAdd/index.tsx

@@ -0,0 +1,737 @@
+import store, { RootState } from "@/store";
+import { Button, Checkbox, Form, Input, Popconfirm, Select } from "antd";
+import React, {
+  useCallback,
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+} from "react";
+import { useSelector } from "react-redux";
+import TextArea from "antd/es/input/TextArea";
+import styles from "./index.module.scss";
+import { MessageFu } from "@/utils/message";
+import ImageLazy from "@/components/ImageLazy";
+import classNames from "classnames";
+import {
+  PlusOutlined,
+  CloseCircleOutlined,
+  UploadOutlined,
+  CloseOutlined,
+  PlayCircleOutlined,
+} from "@ant-design/icons";
+import {
+  getGoodsInfoByIdAPI,
+  getGoodsSaveAPI,
+  goodsUploadAPI,
+} from "@/store/action/A3Goods";
+import { baseURL } from "@/utils/http";
+import { FileListType, GoodsTableType } from "@/types";
+import { domShowFu, progressDomFu } from "@/utils/domShow";
+
+type Props = {
+  id: number;
+  closeMoalFu: () => void;
+  addListFu: () => void;
+  editListFu: () => void;
+};
+
+function GoodsAdd({ id, closeMoalFu, addListFu, editListFu }: Props) {
+  // 上传附件的信息
+  const [fileList, setFileList] = useState({
+    model: {} as FileListType,
+    img: [] as FileListType[],
+    audio: {} as FileListType,
+    video: {} as FileListType,
+  });
+
+  // 表单的ref
+  const FormBoxRef = useRef<any>({});
+
+  // 文件的dirCode码
+  const [dirCode, setDirCode] = useState("");
+
+  const getInfoInAPIFu = useCallback(async (id: number) => {
+    const res = await getGoodsInfoByIdAPI(id);
+    FormBoxRef.current.setFieldsValue(res.data.entity);
+    setCover(res.data.entity.thumb);
+
+    if (res.data.entity.type) setTypeCheck(res.data.entity.type.split(","));
+
+    const data: FileListType[] = res.data.file;
+    const obj = {
+      model: {} as FileListType,
+      img: [] as FileListType[],
+      audio: {} as FileListType,
+      video: {} as FileListType,
+    };
+
+    data.forEach((v) => {
+      if (v.type === "img") obj.img.push(v);
+      else obj[v.type!] = v;
+    });
+    setFileList(obj);
+    setDirCode(res.data.entity.dirCode);
+  }, []);
+
+  useEffect(() => {
+    if (id > 0) getInfoInAPIFu(id);
+    else {
+      setDirCode(Date.now() + "");
+      FormBoxRef.current.setFieldsValue({
+        topic: "不展示",
+        display: 1,
+        isBarrage: 0,
+      });
+    }
+  }, [getInfoInAPIFu, id]);
+
+  // 从仓库获取下拉列表数据
+  const dictList = useSelector(
+    (state: RootState) => state.layoutStore.dictList
+  );
+
+  // 上传封面图的ref
+  const [coverCheck, setCoverCheck] = useState(false);
+  const [cover, setCover] = useState("");
+  const myInput = useRef<HTMLInputElement>(null);
+
+  // 上传封面图
+  const handeUpPhoto = useCallback(
+    async (e: React.ChangeEvent<HTMLInputElement>) => {
+      if (e.target.files) {
+        // 拿到files信息
+        const filesInfo = e.target.files[0];
+        // 校验格式
+        const type = ["image/jpeg", "image/png"];
+        if (!type.includes(filesInfo.type)) {
+          e.target.value = "";
+          return MessageFu.warning("只支持jpg、png格式!");
+        }
+        // 校验大小
+        if (filesInfo.size > 20 * 1024 * 1024) {
+          e.target.value = "";
+          return MessageFu.warning("最大支持20M!");
+        }
+        // 创建FormData对象
+        const fd = new FormData();
+        // 把files添加进FormData对象(‘photo’为后端需要的字段)
+        fd.append("type", "thumb");
+        fd.append("dirCode", dirCode);
+        fd.append("file", filesInfo);
+
+        e.target.value = "";
+
+        const res: any = await goodsUploadAPI(fd);
+        if (res.code === 0) {
+          MessageFu.success("上传成功!");
+          setCover(res.data.filePath);
+        }
+        domShowFu("#UpAsyncLoding", false);
+        progressDomFu("0%");
+      }
+    },
+    [dirCode]
+  );
+
+  // 选中附件类型
+  const [typeCheck, setTypeCheck] = useState<any>([]);
+  const [typeOk, setTypeOk] = useState(false);
+
+  const typeCheckArr = useMemo(() => {
+    return [
+      { label: "模型", value: "model" },
+      { label: "图片", value: "img" },
+      { label: "音频", value: "audio" },
+      { label: "视频", value: "video" },
+    ];
+  }, []);
+
+  // 附件信息的校验
+
+  const fileCheckFu = useMemo(() => {
+    let flag = false;
+    if (typeCheck.length === 0) flag = true;
+    if (typeCheck.includes("model") && !fileList.model.id) flag = true;
+    if (typeCheck.includes("img") && fileList.img.length === 0) flag = true;
+    if (typeCheck.includes("audio") && !fileList.audio.id) flag = true;
+    if (typeCheck.includes("video") && !fileList.video.id) flag = true;
+    return flag;
+  }, [fileList, typeCheck]);
+
+  // 点击上传附件按钮
+  const myInput2 = useRef<HTMLInputElement>(null);
+
+  const [fileOneType, setFileOneType] = useState("");
+
+  useEffect(() => {
+    if (fileOneType) myInput2.current?.click();
+  }, [fileOneType]);
+
+  const upFileFu = useCallback((type: string) => {
+    setFileOneType("");
+    window.setTimeout(() => {
+      setFileOneType(type);
+    }, 100);
+  }, []);
+
+  // 上传附件的处理函数
+  const handeUpPhoto2 = useCallback(
+    async (e: React.ChangeEvent<HTMLInputElement>) => {
+      if (e.target.files) {
+        // 拿到files信息
+        const filesInfo = e.target.files[0];
+
+        let anType = ["image/jpeg", "image/png", "image/gif"];
+        let anTit1 = "只支持png、jpg、gif和jpeg格式!";
+        let anTit2 = "最大支持20M!";
+        let anSize = 20 * 1024 * 1024;
+
+        if (fileOneType === "audio") {
+          anType = ["audio/mpeg"];
+          anTit1 = "只支持mp3格式!";
+          anTit2 = "最大支持10M!";
+          anSize = 10 * 1024 * 1024;
+        } else if (fileOneType === "video") {
+          anType = ["video/mp4"];
+          anTit1 = "只支持mp4格式!";
+          anTit2 = "最大支持500M!";
+          anSize = 500 * 1024 * 1024;
+        } else if (fileOneType === "model") {
+          anType = [""];
+          anTit1 = "只支持4dage格式!";
+          anTit2 = "最大支持500M!";
+          anSize = 500 * 1024 * 1024;
+        }
+
+        // 校验格式
+        if (fileOneType !== "model") {
+          if (!anType.includes(filesInfo.type)) {
+            e.target.value = "";
+            return MessageFu.warning(anTit1);
+          }
+        } else {
+          if (!filesInfo.name.includes(".4dage")) {
+            e.target.value = "";
+            return MessageFu.warning(anTit1);
+          }
+        }
+
+        // 校验大小
+        if (filesInfo.size > anSize) {
+          e.target.value = "";
+          return MessageFu.warning(anTit2);
+        }
+        // 创建FormData对象
+        const fd = new FormData();
+        // 把files添加进FormData对象(‘photo’为后端需要的字段)
+        fd.append("type", fileOneType);
+        fd.append("dirCode", dirCode);
+        fd.append("file", filesInfo);
+
+        e.target.value = "";
+
+        const res: any = await goodsUploadAPI(fd);
+
+        if (res.code === 0) {
+          MessageFu.success("上传成功!");
+          if (fileOneType === "img")
+            setFileList({ ...fileList, img: [res.data, ...fileList.img] });
+          else setFileList({ ...fileList, [fileOneType]: res.data });
+        }
+        domShowFu("#UpAsyncLoding", false);
+        progressDomFu("0%");
+      }
+    },
+    [dirCode, fileList, fileOneType]
+  );
+
+  // 附件图片的拖动
+  const [dragImg, setDragImg] = useState<any>(null);
+
+  const handleDragOver = useCallback(
+    (e: React.DragEvent<HTMLDivElement>, item: FileListType) => {
+      e.dataTransfer.dropEffect = "move";
+    },
+    []
+  );
+
+  const handleDragEnter = useCallback(
+    (e: React.DragEvent<HTMLDivElement>, item: FileListType) => {
+      e.dataTransfer.effectAllowed = "move";
+      if (item === dragImg) return;
+      const newItems = [...fileList.img]; //拷贝一份数据进行交换操作。
+      const src = newItems.indexOf(dragImg); //获取数组下标
+      const dst = newItems.indexOf(item);
+      newItems.splice(dst, 0, ...newItems.splice(src, 1)); //交换位置
+      setFileList({ ...fileList, img: newItems });
+    },
+    [dragImg, fileList]
+  );
+
+  // 删除某一张图片
+  const delImgListFu = useCallback(
+    (id: number) => {
+      const newItems = fileList.img.filter((v) => v.id !== id);
+      setFileList({ ...fileList, img: newItems });
+    },
+    [fileList]
+  );
+
+  // 没有通过校验
+  const onFinishFailed = useCallback(() => {
+    setCoverCheck(true);
+    setTypeOk(true);
+    return MessageFu.warning("有表单不符号规则!");
+  }, []);
+
+  // 通过校验点击确定
+  const onFinish = useCallback(
+    async (value: GoodsTableType) => {
+      console.log("通过校验,点击确定");
+      setCoverCheck(true);
+      setTypeOk(true);
+      if (typeCheck.length === 0 || cover === "" || fileCheckFu)
+        return MessageFu.warning("有表单不符号规则!");
+
+      const fileIds = [];
+      if (fileList.model.id && typeCheck.includes("model"))
+        fileIds.push(fileList.model.id);
+      if (fileList.audio.id && typeCheck.includes("audio"))
+        fileIds.push(fileList.audio.id);
+      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);
+        });
+      }
+
+      const obj = {
+        ...value,
+        id: id > 0 ? id : null,
+        dirCode,
+        fileIds: fileIds.join(","),
+        thumb: cover,
+        type: typeCheck.join(","),
+      } as GoodsTableType;
+      const res = await getGoodsSaveAPI(obj);
+      if (res.code === 0) {
+        MessageFu.success(id > 0 ? "编辑成功!" : "新增成功!");
+        closeMoalFu();
+        if (id > 0) editListFu();
+        else addListFu();
+      }
+    },
+    [
+      typeCheck,
+      cover,
+      fileCheckFu,
+      fileList.model.id,
+      fileList.audio.id,
+      fileList.video.id,
+      fileList.img,
+      id,
+      dirCode,
+      closeMoalFu,
+      editListFu,
+      addListFu,
+    ]
+  );
+
+  return (
+    <div className={styles.GoodsAdd}>
+      <div className="pageTitle">{id > 0 ? "编辑馆藏" : "新增馆藏"}</div>
+      <div className="main mySorrl">
+        <Form
+          ref={FormBoxRef}
+          name="basic"
+          labelCol={{ span: 3 }}
+          onFinish={onFinish}
+          onFinishFailed={onFinishFailed}
+          autoComplete="off"
+        >
+          <Form.Item
+            label="名称"
+            name="name"
+            rules={[{ required: true, message: "请输入名称!" }]}
+            getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+          >
+            <Input maxLength={25} showCount placeholder="请输入内容" />
+          </Form.Item>
+
+          <Form.Item
+            label="类别"
+            name="dictTexture"
+            rules={[{ required: true, message: "请选择类别!" }]}
+          >
+            <Select
+              placeholder="请选择"
+              style={{ width: 400 }}
+              options={dictList["texture"].slice(1)}
+            />
+          </Form.Item>
+
+          <Form.Item
+            label="年代"
+            name="dictAge"
+            rules={[{ required: true, message: "请选择年代!" }]}
+          >
+            <Select
+              placeholder="请选择"
+              style={{ width: 400 }}
+              options={dictList["age"].slice(1)}
+            />
+          </Form.Item>
+
+          <Form.Item
+            label="简介"
+            name="description"
+            // getValueFromEvent={(e) => e.target.value.trim()}
+          >
+            <TextArea
+              rows={4}
+              placeholder="请输入内容"
+              showCount
+              maxLength={200}
+            />
+          </Form.Item>
+
+          {/* -----上传封面图片 */}
+          <div className="myformBox myformBox0">
+            <input
+              id="upInput"
+              type="file"
+              accept=".png,.jpg,.jpeg"
+              ref={myInput}
+              onChange={(e) => handeUpPhoto(e)}
+            />
+            <input
+              id="upInput2"
+              type="file"
+              accept={
+                fileOneType === "img"
+                  ? ".gif,.png,.jpg,.jpeg"
+                  : fileOneType === "audio"
+                  ? ".mp3"
+                  : fileOneType === "model"
+                  ? ".4dage"
+                  : ".mp4"
+              }
+              ref={myInput2}
+              onChange={(e) => handeUpPhoto2(e)}
+            />
+            <div className="label">
+              <span>*</span> 封面图:
+            </div>
+            <div className="fileBoxRow_r">
+              <div
+                hidden={cover !== ""}
+                className="fileBoxRow_up"
+                onClick={() => myInput.current?.click()}
+              >
+                <PlusOutlined />
+              </div>
+              <div className="fileBoxRow_r_img" hidden={cover === ""}>
+                {cover ? (
+                  <ImageLazy width={100} height={100} src={cover} />
+                ) : null}
+
+                <Popconfirm
+                  title="删除后无法恢复,是否删除?"
+                  okText="删除"
+                  cancelText="取消"
+                  onConfirm={() => setCover("")}
+                >
+                  <div className="clearCover">
+                    <CloseCircleOutlined />
+                  </div>
+                </Popconfirm>
+              </div>
+              <div className="fileBoxRow_r_tit">
+                支持png、jpg和jpeg的图片格式;最大支持20M。
+                <br />
+                <div
+                  className={classNames(
+                    "noUpThumb",
+                    !cover && coverCheck ? "noUpThumbAc" : ""
+                  )}
+                >
+                  请上传封面图!
+                </div>
+              </div>
+            </div>
+          </div>
+
+          {/* 选中文件类型和上传附件 */}
+          <div className="myformBox">
+            <div className="label">
+              <span>*</span> 文件类型:
+            </div>
+            <div className="myformBoxR">
+              <Checkbox.Group
+                options={typeCheckArr}
+                value={typeCheck}
+                onChange={(e) => setTypeCheck(e)}
+                // onChange={(e) => console.log(e)}
+              />
+            </div>
+          </div>
+
+          {/* -----------模型上传 */}
+          <div
+            className="myformBox myformBox2"
+            hidden={!typeCheck.includes("model")}
+          >
+            <div className="label">
+              <span>*</span> 模型:
+            </div>
+            {fileList.model.id ? (
+              <div className="fileInfo">
+                <a
+                  href={baseURL + fileList.model.filePath}
+                  download
+                  target="_blank"
+                  className="upSuccTxt"
+                  rel="noreferrer"
+                >
+                  {fileList.model.fileName}
+                </a>
+
+                <Popconfirm
+                  title="删除后无法恢复,是否删除?"
+                  okText="删除"
+                  cancelText="取消"
+                  onConfirm={() => setFileList({ ...fileList, model: {} })}
+                >
+                  <div className="clearCover">
+                    <CloseCircleOutlined />
+                  </div>
+                </Popconfirm>
+              </div>
+            ) : (
+              <>
+                <Button
+                  onClick={() => upFileFu("model")}
+                  icon={<UploadOutlined />}
+                >
+                  上传
+                </Button>
+
+                <div className="fileTit">
+                  仅支持4dage格式的模型文件,大小不能超过500M。
+                </div>
+              </>
+            )}
+          </div>
+
+          {/* -----------图片上传 */}
+          <div
+            className="myformBox myformBox3"
+            hidden={!typeCheck.includes("img")}
+          >
+            <div className="label">
+              <span>*</span> 图片:
+            </div>
+            <>
+              <div className="fileBoxRow_r">
+                <div className="upImgBox">
+                  <div
+                    hidden={!!fileList.img.length && fileList.img.length >= 9}
+                    className="fileBoxRow_up"
+                    onClick={() => upFileFu("img")}
+                  >
+                    <PlusOutlined />
+                  </div>
+                  {fileList.img.map((v) => (
+                    <div
+                      className="fileBoxRow_r_img"
+                      key={v.id}
+                      draggable="true"
+                      onDragStart={() => setDragImg(v)}
+                      onDragOver={(e) => handleDragOver(e, v)}
+                      onDragEnter={(e) => handleDragEnter(e, v)}
+                      onDragEnd={() => setDragImg(null)}
+                    >
+                      {v.filePath ? (
+                        <ImageLazy
+                          noLook={dragImg ? true : false}
+                          width={100}
+                          height={100}
+                          src={v.filePath}
+                        />
+                      ) : null}
+
+                      <Popconfirm
+                        title="删除后无法恢复,是否删除?"
+                        okText="删除"
+                        cancelText="取消"
+                        onConfirm={() => delImgListFu(v.id!)}
+                      >
+                        <div className="clearCover">
+                          <CloseOutlined />
+                        </div>
+                      </Popconfirm>
+                    </div>
+                  ))}
+                </div>
+                <div className="fileTit">
+                  {fileList.img.length && fileList.img.length >= 2 ? (
+                    <>
+                      按住鼠标可拖动图片调整顺序。
+                      <br />
+                    </>
+                  ) : null}
+                  支持png、jpg、gif和jpeg的图片格式;最大支持20M;最多支持9张。
+                </div>
+              </div>
+            </>
+          </div>
+
+          {/* -----------音频上传 */}
+          <div
+            className="myformBox myformBox2"
+            hidden={!typeCheck.includes("audio")}
+          >
+            <div className="label">
+              <span>*</span> 音频:
+            </div>
+            {fileList.audio.id ? (
+              <div className="fileInfo">
+                <a
+                  href={baseURL + fileList.audio.filePath}
+                  download
+                  target="_blank"
+                  className="upSuccTxt"
+                  rel="noreferrer"
+                >
+                  {fileList.audio.fileName}
+                </a>
+
+                <Popconfirm
+                  title="删除后无法恢复,是否删除?"
+                  okText="删除"
+                  cancelText="取消"
+                  onConfirm={() => setFileList({ ...fileList, audio: {} })}
+                >
+                  <div className="clearCover">
+                    <CloseCircleOutlined />
+                  </div>
+                </Popconfirm>
+              </div>
+            ) : (
+              <>
+                <Button
+                  onClick={() => upFileFu("audio")}
+                  icon={<UploadOutlined />}
+                >
+                  上传
+                </Button>
+
+                <div className="fileTit">
+                  仅支持MP3格式的音频文件,大小不得超过10MB。
+                </div>
+              </>
+            )}
+          </div>
+
+          {/* -----------视频上传 */}
+          <div
+            className="myformBox myformBox2"
+            hidden={!typeCheck.includes("video")}
+          >
+            <div className="label">
+              <span>*</span> 视频:
+            </div>
+            {fileList.video.id ? (
+              <div className="fileInfo">
+                <div className="upSuccTxt">{fileList.video.fileName}</div>
+                <div
+                  className="clearCover"
+                  hidden={!fileList.video.filePath}
+                  onClick={() =>
+                    store.dispatch({
+                      type: "layout/lookVideo",
+                      payload: fileList.video.filePath!,
+                    })
+                  }
+                >
+                  <PlayCircleOutlined />
+                </div>
+
+                <Popconfirm
+                  title="删除后无法恢复,是否删除?"
+                  okText="删除"
+                  cancelText="取消"
+                  onConfirm={() => setFileList({ ...fileList, video: {} })}
+                >
+                  <div className="clearCover">
+                    <CloseCircleOutlined />
+                  </div>
+                </Popconfirm>
+              </div>
+            ) : (
+              <>
+                <Button
+                  onClick={() => upFileFu("video")}
+                  icon={<UploadOutlined />}
+                >
+                  上传
+                </Button>
+
+                <div className="fileTit">
+                  仅支持MP4格式的视频文件,大小不得超过500MB。
+                </div>
+              </>
+            )}
+          </div>
+
+          <div
+            className={classNames(
+              "noUpThumb noUpThumb2",
+              fileCheckFu && typeOk ? "noUpThumbAc" : ""
+            )}
+          >
+            请至少选择一个文件类型,并上传对应附件!
+          </div>
+
+          <Form.Item
+            label="展示状态"
+            name="display"
+            rules={[{ required: true, message: "请选择展示状态!" }]}
+          >
+            <Select
+              placeholder="请选择"
+              style={{ width: 400 }}
+              options={[
+                { value: 1, label: "展示" },
+                { value: 0, label: "不展示" },
+              ]}
+            />
+          </Form.Item>
+
+          {/* 确定和取消按钮 */}
+          <br />
+          <Form.Item wrapperCol={{ offset: 9, span: 16 }}>
+            <Button type="primary" htmlType="submit">
+              提交
+            </Button>
+            &emsp;
+            <Popconfirm
+              title="放弃编辑后,信息将不会保存!"
+              okText="放弃"
+              cancelText="取消"
+              onConfirm={closeMoalFu}
+            >
+              <Button>取消</Button>
+            </Popconfirm>
+          </Form.Item>
+        </Form>
+      </div>
+    </div>
+  );
+}
+
+const MemoGoodsAdd = React.memo(GoodsAdd);
+
+export default MemoGoodsAdd;

+ 41 - 3
houtai/src/pages/A3Goods/index.module.scss

@@ -1,5 +1,43 @@
-.Goods{
-  :global{
-    
+.Goods {
+  position: relative;
+  :global {
+    .goodsTop {
+      border-radius: 10px;
+      background-color: #fff;
+    }
+
+    .searchBox {
+      padding: 10px 15px 0;
+      display: flex;
+      flex-wrap: wrap;
+
+      .searchRow {
+        margin-bottom: 20px;
+        margin-right: 20px;
+      }
+      .searchRow2{
+        margin-right: 0;
+      }
+    }
+
+    .tableBox {
+      border-radius: 10px;
+      overflow: hidden;
+      margin-top: 20px;
+      height: calc(100% - 128px);
+      background-color: #fff;
+
+      .ant-table-body {
+        height: 560px;
+        overflow-y: auto !important;
+        overflow-y: overlay !important;
+
+        .ant-table-row {
+          .ant-table-cell {
+            padding: 8px;
+          }
+        }
+      }
+    }
   }
 }

+ 313 - 5
houtai/src/pages/A3Goods/index.tsx

@@ -1,12 +1,320 @@
-import React from "react";
+import { RootState } from "@/store";
+import { getGoodsListAPI, goodsRemoveAPI } from "@/store/action/A3Goods";
+import { MessageFu } from "@/utils/message";
+import { Input, Select, DatePicker, Button, Table, Popconfirm } from "antd";
+import React, {
+  useCallback,
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+} from "react";
+import { useDispatch, useSelector } from "react-redux";
 import styles from "./index.module.scss";
- function Goods() {
-  
+import ImageLazy from "@/components/ImageLazy";
+import { GoodsTableType } from "@/types";
+import GoodsAdd from "./GoodsAdd";
+
+const { RangePicker } = DatePicker;
+function Goods() {
+  const dispatch = useDispatch();
+  const pageNumRef = useRef(1);
+  const pagePageRef = useRef(10);
+
+  // 从仓库获取下拉列表数据
+  const dictList = useSelector(
+    (state: RootState) => state.layoutStore.dictList
+  );
+
+  // 从仓库获取表格列表信息
+  const tableInfo = useSelector(
+    (state: RootState) => state.goodsReducer.tableInfo
+  );
+
+  // 顶部筛选
+  const [tableSelect, setTableSelect] = useState({
+    searchKey: "",
+    dictTexture: "",
+    dictAge: "",
+    startTime: "",
+    endTime: "",
+    display: -1,
+    pageSize: 10,
+    pageNum: 1,
+  });
+
+  // 封装发送请求的函数
+
+  const getList = useCallback(async () => {
+    const data = {
+      ...tableSelect,
+      display: tableSelect.display === -1 ? null : tableSelect.display,
+      pageNum: pageNumRef.current,
+    };
+    dispatch(getGoodsListAPI(data));
+  }, [dispatch, tableSelect]);
+
+  // 当前页码统一
+  useEffect(() => {
+    pageNumRef.current = tableSelect.pageNum;
+    pagePageRef.current = tableSelect.pageSize;
+  }, [tableSelect.pageNum, tableSelect.pageSize]);
+
+  useEffect(() => {
+    getList();
+  }, [getList]);
+
+  // 名称的输入
+  const nameTime = useRef(-1);
+  const nameChange = useCallback(
+    (e: React.ChangeEvent<HTMLInputElement>) => {
+      clearTimeout(nameTime.current);
+      nameTime.current = window.setTimeout(() => {
+        setTableSelect({
+          ...tableSelect,
+          searchKey: e.target.value,
+          pageNum: 1,
+        });
+      }, 500);
+    },
+    [tableSelect]
+  );
+
+  // 时间选择器改变
+  const timeChange = (date: any, dateString: any) => {
+    let startTime = "";
+    let endTime = "";
+    if (dateString[0] && dateString[1]) {
+      startTime = dateString[0] + " 00:00:00";
+      endTime = dateString[1] + " 23:59:59";
+    }
+    setTableSelect({ ...tableSelect, startTime, endTime, pageNum: 1 });
+  };
+
+  // 点击重置
+  const [inputKey, setInputKey] = useState(1);
+  const resetSelectFu = useCallback(() => {
+    // 把2个输入框和时间选择器清空
+    setInputKey(Date.now());
+    setTableSelect({
+      searchKey: "",
+      dictTexture: "",
+      dictAge: "",
+      startTime: "",
+      endTime: "",
+      display: -1,
+      pageSize: 10,
+      pageNum: 1,
+    });
+  }, []);
+
+  // ----------关于表格的数据
+
+  // 页码变化
+  const paginationChange = useCallback(
+    () => (pageNum: number, pageSize: number) => {
+      pageNumRef.current = pageNum;
+      pagePageRef.current = pageSize;
+      setTableSelect({ ...tableSelect, pageNum, pageSize });
+    },
+    [tableSelect]
+  );
+
+  // 点击删除
+  const delTableFu = useCallback(
+    async (id: number) => {
+      const res = await goodsRemoveAPI(id);
+      if (res.code === 0) {
+        MessageFu.success("删除成功!");
+        getList();
+      }
+    },
+    [getList]
+  );
+
+  const columns = useMemo(() => {
+    return [
+      {
+        title: "名称",
+        dataIndex: "name",
+      },
+
+      {
+        title: "类别",
+        dataIndex: "dictTexture",
+      },
+      {
+        title: "年代",
+        dataIndex: "dictAge",
+      },
+      {
+        title: "简介",
+        render: (item: GoodsTableType) =>
+          item.description ? (
+            item.description.length >= 25 ? (
+              <span style={{ cursor: "pointer" }} title={item.description}>
+                {item.description.substring(0, 25) + "..."}
+              </span>
+            ) : (
+              item.description
+            )
+          ) : (
+            "(空)"
+          ),
+      },
+      {
+        title: "图片",
+        render: (item: GoodsTableType) => (
+          <div className="tableImgAuto">
+            <ImageLazy width={60} height={60} src={item.thumb!} />
+          </div>
+        ),
+      },
+      {
+        title: "最近编辑时间",
+        dataIndex: "updateTime",
+      },
+
+      {
+        title: "展示状态",
+        render: (item: GoodsTableType) =>
+          item.display === 1 ? "展示" : "不展示",
+      },
+
+      {
+        title: "操作",
+        render: (item: GoodsTableType) => (
+          <>
+            <Button size="small" type="text" onClick={() => setAddId(item.id!)}>
+              编辑
+            </Button>
+            <Popconfirm
+              title="删除后无法恢复,是否删除?"
+              okText="删除"
+              cancelText="取消"
+              onConfirm={() => delTableFu(item.id!)}
+            >
+              <Button size="small" type="text" danger>
+                删除
+              </Button>
+            </Popconfirm>
+          </>
+        ),
+      },
+    ];
+  }, [delTableFu]);
+
+  // 新增或者编辑的弹窗
+  const [addId, setAddId] = useState(0);
+
   return (
     <div className={styles.Goods}>
-      <h1>Goods</h1>
+      <div className="goodsTop">
+        <div className="pageTitle">馆藏管理</div>
+        {/* 搜索信息 */}
+        <div className="searchBox">
+          <div className="searchRow">
+            <span>名称:</span>
+            <Input
+              key={inputKey}
+              maxLength={25}
+              style={{ width: 140 }}
+              placeholder="请输入关键字"
+              allowClear
+              onChange={(e) => nameChange(e)}
+            />
+          </div>
+
+          <div className="searchRow">
+            <span>类别:</span>
+            <Select
+              placeholder="请选择"
+              style={{ width: 140 }}
+              value={tableSelect.dictTexture}
+              onChange={(e) =>
+                setTableSelect({ ...tableSelect, dictTexture: e, pageNum: 1 })
+              }
+              options={dictList["texture"]}
+            />
+          </div>
+
+          <div className="searchRow">
+            <span>年代:</span>
+            <Select
+              placeholder="请选择"
+              style={{ width: 140 }}
+              value={tableSelect.dictAge}
+              onChange={(e) =>
+                setTableSelect({ ...tableSelect, dictAge: e, pageNum: 1 })
+              }
+              options={dictList["age"]}
+            />
+          </div>
+
+          <div className="searchRow">
+            <span>最近编辑日期:</span>
+            <RangePicker
+              style={{ width: 230 }}
+              key={inputKey}
+              onChange={timeChange}
+            />
+          </div>
+
+          <div className="searchRow">
+            <span>展示状态:</span>
+            <Select
+              placeholder="请选择"
+              style={{ width: 80 }}
+              value={tableSelect.display}
+              onChange={(e) =>
+                setTableSelect({ ...tableSelect, display: e, pageNum: 1 })
+              }
+              options={[
+                { value: -1, label: "全部" },
+                { value: 1, label: "开启" },
+                { value: 0, label: "关闭" },
+              ]}
+            />
+          </div>
+
+          <div className="searchRow searchRow2">
+            <Button onClick={resetSelectFu}>重置</Button>&emsp;&emsp;
+            <Button type="primary" onClick={() => setAddId(-1)}>
+              新增
+            </Button>
+          </div>
+        </div>
+      </div>
+      {/* 表格主体 */}
+      <div className="tableBox">
+        <Table
+          scroll={{ y: 560 }}
+          dataSource={tableInfo.list}
+          columns={columns}
+          rowKey="id"
+          pagination={{
+            showQuickJumper: true,
+            position: ["bottomCenter"],
+            showSizeChanger: true,
+            current: tableSelect.pageNum,
+            pageSize: tableSelect.pageSize,
+            total: tableInfo.total,
+            onChange: paginationChange(),
+          }}
+        />
+      </div>
+
+      {/* 新增和编辑的弹窗 */}
+      {addId !== 0 ? (
+        <GoodsAdd
+          id={addId}
+          closeMoalFu={() => setAddId(0)}
+          addListFu={resetSelectFu}
+          editListFu={getList}
+        />
+      ) : null}
     </div>
-  )
+  );
 }
 
 const MemoGoods = React.memo(Goods);

+ 9 - 6
houtai/src/pages/Layout/index.tsx

@@ -15,7 +15,7 @@ import history from "@/utils/history";
 import { Button, Form, Input, Modal, Popconfirm } from "antd";
 import { Base64 } from "js-base64";
 import encodeStr from "@/utils/pass";
-import { passWordEditAPI } from "@/store/action/layout";
+import { getDictListAPI, passWordEditAPI } from "@/store/action/layout";
 import { getTokenInfo, removeTokenInfo } from "@/utils/storage";
 import { useDispatch } from "react-redux";
 import inco1 from "@/assets/img/inco1.png";
@@ -28,7 +28,7 @@ import inco2Ac from "@/assets/img/inco2Ac.png";
 import inco3Ac from "@/assets/img/inco3Ac.png";
 import inco4Ac from "@/assets/img/inco4Ac.png";
 import inco5Ac from "@/assets/img/inco5Ac.png";
-import logonImg from '@/assets/img/logo2.png'
+import logonImg from "@/assets/img/logo2.png";
 import { MessageFu } from "@/utils/message";
 
 const NotFound = React.lazy(() => import("@/components/NotFound"));
@@ -83,7 +83,7 @@ function Layout() {
 
   // 进页面获取所有下拉信息
   useEffect(() => {
-    // dispatch(getDictListAPI());
+    dispatch(getDictListAPI());
   }, [dispatch]);
 
   // 点击跳转
@@ -139,7 +139,7 @@ function Layout() {
     removeTokenInfo();
     // history.push("/login");
     // 跳到前台页面
-    window.location.href='/web/index.html'
+    window.location.href = "/web/index.html";
   };
 
   return (
@@ -147,7 +147,7 @@ function Layout() {
       {/* 左边 */}
       <div className="layoutLeft">
         <div className="layoutLeftTop">
-        <img src={logonImg} alt="" />
+          <img src={logonImg} alt="" />
         </div>
         {/* 左边主体 */}
         <div className="layoutLeftMain">
@@ -238,7 +238,10 @@ function Layout() {
           <Form.Item
             label="新密码"
             name="newPassword"
-            rules={[{ required: true, message: "不能为空!" }]}
+            rules={[
+              { required: true, message: "不能为空!" },
+              { min: 6, max: 15, message: "密码长度为6-15个字符!" },
+            ]}
           >
             <Input.Password
               maxLength={15}

+ 69 - 0
houtai/src/store/action/A3Goods.ts

@@ -0,0 +1,69 @@
+import { GoodsTableType } from "@/types";
+import { domShowFu, progressDomFu } from "@/utils/domShow";
+import http from "@/utils/http";
+import axios from "axios";
+import store, { AppDispatch } from "..";
+/**
+ * 获取列表数据
+ */
+export const getGoodsListAPI = (data: any) => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post("cms/goods/pageList", data);
+    dispatch({
+      type: "goods/getList",
+      payload: { list: res.data.records, total: res.data.total },
+    });
+  };
+};
+
+/**
+ * 内容-是否显示
+ */
+export const goodsDisplayAPI = (id: number, display: number) => {
+  return http.get(`cms/goods/display/${id}/${display}`);
+};
+
+/**
+ * 删除藏品
+ */
+export const goodsRemoveAPI = (id: number) => {
+  return http.get(`cms/goods/remove/${id}`);
+};
+
+const CancelToken = axios.CancelToken;
+/**
+ * 上传封面图和附件
+ */
+export const goodsUploadAPI = (data: any) => {
+  domShowFu("#UpAsyncLoding", true);
+
+  return http.post("cms/goods/upload", data, {
+    timeout: 50000,
+    // 显示进度条
+    onUploadProgress: (e: any) => {
+      const complete = (e.loaded / e.total) * 100 || 0;
+      progressDomFu(complete + "%");
+    },
+    // 取消上传
+    cancelToken: new CancelToken(function executor(c) {
+      store.dispatch({
+        type: "layout/closeUpFile",
+        payload: { fu: c, state: true },
+      });
+    }),
+  });
+};
+
+/**
+ * 新增|编辑
+ */
+export const getGoodsSaveAPI = (data: GoodsTableType) => {
+  return http.post("cms/goods/save", data);
+};
+
+/**
+ * 通过id获取详情
+ */
+export const getGoodsInfoByIdAPI = (id: number) => {
+  return http.get(`cms/goods/detail/${id}`);
+};

+ 23 - 1
houtai/src/store/action/layout.ts

@@ -1,4 +1,6 @@
+import { DictListTypeAPI, DictListTypeObj } from "@/types";
 import http from "@/utils/http";
+import { AppDispatch } from "..";
 
 /**
  * 用户登录接口
@@ -12,4 +14,24 @@ export const userLoginAPI = (data: any) => {
  */
 export const passWordEditAPI = (data: any) => {
   return http.post("sys/user/updatePwd", { ...data });
-};
+};
+
+/**
+ * 获取下拉框数据
+ */
+export const getDictListAPI = () => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.get("cms/dict/getList");
+    const list: DictListTypeAPI[] = res.data;
+    const obj = {
+      age: [{ label: "全部", value: "", type: "age" }],
+      texture: [{ label: "全部", value: "", type: "texture" }],
+    } as DictListTypeObj;
+    list.forEach((v) => {
+      if (obj[v.type])
+        obj[v.type].push({ label: v.name, value: v.name, type: v.type });
+    });
+
+    dispatch({ type: "layout/getDictList", payload: obj });
+  };
+};

+ 30 - 0
houtai/src/store/reducer/A3Goods.ts

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

+ 3 - 1
houtai/src/store/reducer/index.ts

@@ -1,6 +1,7 @@
 // 导入合并reducer的依赖
 import { combineReducers } from 'redux'
 import newsReducer from './A2News'
+import goodsReducer from './A3Goods'
 
 // 导入 登录 模块的 reducer
 import layoutReducer from './layout'
@@ -8,7 +9,8 @@ import layoutReducer from './layout'
 // 合并 reducer
 const rootReducer = combineReducers({
   layoutStore: layoutReducer,
-  newsReducer:newsReducer
+  newsReducer:newsReducer,
+  goodsReducer:goodsReducer
 })
 
 // 默认导出

+ 12 - 0
houtai/src/store/reducer/layout.ts

@@ -1,3 +1,4 @@
+import { DictListTypeObj } from "@/types";
 import { MessageType } from "@/utils/message";
 
 // 初始化状态
@@ -9,6 +10,13 @@ const initState = {
   },
   // 视频的src
   videoSrc: "",
+
+  // 所有的下拉框数据
+  dictList: {
+    age: [],
+    texture: [],
+  } as DictListTypeObj,
+
   message: {
     txt: "",
     type: "info",
@@ -26,6 +34,7 @@ type LayoutActionType =
   | { type: "layout/lookBigImg"; payload: { url: string; show: boolean } }
   | { type: "layout/lookVideo"; payload: string }
   | { type: "layout/message"; payload: MessageType }
+  | { type: "layout/getDictList"; payload: DictListTypeObj }
   | {
       type: "layout/closeUpFile";
       payload: {
@@ -46,6 +55,9 @@ export default function layoutReducer(
     // 查看视频
     case "layout/lookVideo":
       return { ...state, videoSrc: action.payload };
+    // 所有的下拉框数据
+    case "layout/getDictList":
+      return { ...state, dictList: action.payload };
     // antd轻提示(兼容360浏览器)
     case "layout/message":
       return { ...state, message: action.payload };

+ 33 - 0
houtai/src/types/api/A3Goods.d.ts

@@ -0,0 +1,33 @@
+export type GoodsTableType = {
+  createTime: string;
+  creatorId: number;
+  creatorName: string;
+  description: string;
+  dictAge: string;
+  dictLevel: string;
+  dictSource: string;
+  dictTexture: string;
+  dirCode: string;
+  display: number;
+  fileIds: string;
+  id: number;
+  isBarrage: number;
+  name: string;
+  num: string;
+  thumb: string;
+  topic: string;
+  type: string;
+  updateTime: string;
+  tagType?:string
+  tagCountry?:string
+};
+
+export type FileListType = {
+  fileName?: string;
+  filePath?: string;
+  id?: number;
+  isFrame?: boolean;
+  done?: boolean;
+  type?: "model" | "img" | "audio" | "video";
+};
+

+ 18 - 4
houtai/src/types/api/layot.d.ts

@@ -1,4 +1,18 @@
-export type LoginType = {
-  num: number;
-  active: number;
-}
+
+export type DictListTypeObj = {
+  age: DictListType[];
+  texture: DictListType[];
+};
+
+export type DictListTypeAPI = {
+  createTime: null;
+  creatorId: null;
+  creatorName: string;
+  display: number;
+  id: string;
+  name: string;
+  parentId: null;
+  sort: null;
+  type: "age" | "texture" 
+  updateTime: null;
+};

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

@@ -1,2 +1,3 @@
 export * from './api/layot'
 export * from './api/A2News'
+export * from './api/A3Goods'