shaogen1995 1 year ago
parent
commit
2b97f6e350

+ 4 - 1
pc/public/4dage.js

@@ -68,7 +68,10 @@ var Clamp = function (e, t, i) {
     codeToCh = function (e) {
     codeToCh = function (e) {
         return unescape(e)
         return unescape(e)
     };
     };
-fdage = {},
+fdage = {
+    // 背景颜色透明
+    transparentBackground: true
+},
     function (I) {
     function (I) {
 
 
         function r(e, t, i) {
         function r(e, t, i) {

+ 1 - 1
pc/public/model.html

@@ -19,7 +19,7 @@
   <script>
   <script>
     let url = getQueryVariable("m");
     let url = getQueryVariable("m");
     fdage.embed(url, {
     fdage.embed(url, {
-      // fdage.embed('https://hnbwg.4dage.com' + url, {
+      // fdage.embed('https://ypbwg.4dage.com' + url, {
       // fdage.embed('http://192.168.20.55:8041/api' + url, {
       // fdage.embed('http://192.168.20.55:8041/api' + url, {
       transparentBackground: true,
       transparentBackground: true,
       width: 800,
       width: 800,

+ 1 - 1
pc/public/staticData.js

@@ -1,5 +1,5 @@
 // 开发环境
 // 开发环境
-const staticUrl ='http://localhost:3000'
+const staticUrl ='http://localhost:3000/staticData'
 
 
 // 打包
 // 打包
 // const staticUrl ='/web'
 // const staticUrl ='/web'

BIN
pc/public/staticData/goods/bac.jpg


BIN
pc/public/staticData/map/0.jpg


BIN
pc/src/assets/img/goods/R_left.png


BIN
pc/src/assets/img/goods/R_right.png


BIN
pc/src/assets/img/goods/cur.png


BIN
pc/src/assets/img/goods/curAc.png


BIN
pc/src/assets/img/goods/toBack.png


+ 1 - 0
pc/src/pages/A0Map/index.module.scss

@@ -50,6 +50,7 @@
         // transform:translate();
         // transform:translate();
 
 
         &>img {
         &>img {
+          pointer-events: none;
           width: 100%;
           width: 100%;
           height: 100%;
           height: 100%;
         }
         }

+ 0 - 306
pc/src/pages/A2Main/GoodsSw/index.module.scss

@@ -1,306 +0,0 @@
-.GoodsSw {
-  height: calc(100% - 100px);
-
-  :global {
-    .noInfo {
-      height: calc(100% - 100px);
-      display: flex;
-      justify-content: center;
-      align-items: center;
-      color: var(--themeColor);
-      font-size: 40px;
-      padding-top: 100px;
-    }
-
-    .goddsBox {
-      height: calc(100% - 100px);
-
-
-
-
-      // 第一个自动播发的盒子
-      .goddsSwBox {
-        height: calc(50% - 20px);
-        border-bottom: 1px solid rgba(231, 219, 188, 0.50);
-        position: relative;
-        width: 100%;
-        overflow-x: auto;
-
-        &::-webkit-scrollbar {
-          /*滚动条整体样式*/
-          width: 0px;
-          /*高宽分别对应横竖滚动条的尺寸*/
-          height: 0px;
-        }
-
-
-
-        .goddsSw {
-          display: flex;
-          // position: absolute;
-          // left: 0;
-          // top: 0;
-          height: 100%;
-
-          .goddsRow {
-            min-width: 400px;
-            width: 25vw;
-            color: #fff;
-            padding: 0 10px 0 90px;
-            display: flex;
-            height: 100%;
-
-            .name {
-              width: 40px;
-              margin-right: 20px;
-              word-wrap: break-word;
-              writing-mode: vertical-lr;
-              writing-mode: tb-lr;
-              font-size: 16px;
-              color: var(--themeColor);
-              padding-top: 20px;
-              letter-spacing: 3px;
-              position: relative;
-
-              &::before {
-                content: '';
-                position: absolute;
-                top: 0;
-                left: 7.5px;
-                width: 8px;
-                height: 8px;
-                border-radius: 50%;
-                background-color: var(--themeColor);
-              }
-            }
-
-            .goddsImg {
-              cursor: pointer;
-
-              width: calc(100% - 80px);
-              height: calc(100% - 80px);
-              position: relative;
-
-              &::before {
-                pointer-events: none;
-                content: '';
-                position: absolute;
-                bottom: -80px;
-                left: 50%;
-                transform: translateX(-50%);
-                background: linear-gradient(rgba(231, 219, 188, 0), rgba(231, 219, 188, 1));
-                width: 1px;
-                height: 90px;
-              }
-
-              img {
-                pointer-events: none;
-                object-fit: contain;
-              }
-            }
-          }
-        }
-
-
-      }
-
-
-
-      .goddsSwBox2 {
-        overflow-y: hidden;
-        border-bottom: none;
-        border-top: 1px solid rgba(231, 219, 188, 0.50);
-
-        margin-top: 40px;
-
-        .goddsSw {
-
-          .goddsRow {
-            padding: 0 90px 0 10px;
-
-            .name {
-              position: relative;
-              top: 80px;
-            }
-
-            .goddsImg {
-              top: 80px;
-
-              &::before {
-                bottom: auto;
-                top: -80px;
-                background: linear-gradient(rgba(231, 219, 188, 1), rgba(231, 219, 188, 0));
-              }
-
-            }
-          }
-        }
-      }
-
-
-    }
-
-    .searchBox {
-      height: 100px;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-
-      .searRow {
-        margin: 20px;
-
-
-
-        .ant-select-selector {
-          border-radius: 0 6px 0px 6px;
-          background-color: transparent;
-          color: var(--themeColor);
-          border: 1px solid var(--themeColor);
-
-          .ant-select-selection-search-input::-webkit-input-placeholder {
-            /* WebKit browsers */
-            color: var(--themeColor);
-          }
-
-          .ant-select-selection-search-input:-moz-placeholder {
-            /* Mozilla Firefox 4 to 18 */
-            color: var(--themeColor);
-          }
-
-          .ant-select-selection-search-input::-moz-placeholder {
-            /* Mozilla Firefox 19+ */
-            color: var(--themeColor);
-          }
-
-          .ant-select-selection-search-input:-ms-input-placeholder {
-            /* Internet Explorer 10+ */
-            color: var(--themeColor);
-          }
-
-          .ant-select-selection-item {
-            color: var(--themeColor);
-          }
-
-          .ant-select-selection-placeholder {
-            color: var(--themeColor);
-          }
-
-        }
-
-        .ant-select-arrow {
-          color: var(--themeColor);
-        }
-
-        .anticon-down {
-          color: var(--themeColor);
-        }
-      }
-
-      .ant-input-affix-wrapper {
-        border-radius: 0 6px 0px 6px;
-        background-color: transparent;
-        color: var(--themeColor);
-        border: 1px solid var(--themeColor);
-
-        .ant-input {
-          background-color: transparent;
-          color: var(--themeColor);
-
-          &::-webkit-input-placeholder {
-            /* WebKit browsers */
-            color: var(--themeColor);
-          }
-
-          &:-moz-placeholder {
-            /* Mozilla Firefox 4 to 18 */
-            color: var(--themeColor);
-          }
-
-          &::-moz-placeholder {
-            /* Mozilla Firefox 19+ */
-            color: var(--themeColor);
-          }
-
-          &:-ms-input-placeholder {
-            /* Internet Explorer 10+ */
-            color: var(--themeColor);
-          }
-        }
-
-        .ant-input-clear-icon {
-          color: var(--themeColor);
-        }
-      }
-
-    }
-
-    // 藏品详情
-    .goodsInfoBox {
-      position: absolute;
-      top: 0;
-      left: 0;
-      width: 100%;
-      height: 100%;
-      opacity: 0;
-      pointer-events: none;
-      transition: all .3s;
-      backdrop-filter: blur(10px);
-      padding-top: 30px;
-
-      &>div {
-        color: #fff;
-      }
-    }
-
-    .goodsInfoBoxAc {
-      opacity: 1;
-      pointer-events: auto;
-    }
-
-    .curTitBox {
-      opacity: 0;
-      pointer-events: none;
-      border-radius: 0 0 4px 4px;
-      border-top: 3px solid #b6ab97;
-      position: absolute;
-      top: 50%;
-      left: 50%;
-      transform: translate(-50%, -50%);
-      width: 300px;
-      height: 370px;
-      background-color: #726b56;
-
-      .curClose {
-        position: absolute;
-        right: 15px;
-        top: 15px;
-        cursor: pointer;
-        color: #98856f;
-        font-size: 24px;
-      }
-
-      .curImg {
-        margin: 70px auto 30px;
-        width: 213px;
-        height: 213px;
-        position: relative;
-
-        &>img {
-          position: absolute;
-          top: 0;
-          left: 0;
-          width: 100%;
-          height: 100%;
-          opacity: 1;
-          transition: all 2s;
-        }
-      }
-
-      &>p {
-        font-size: 14px;
-        color: #fff;
-        text-align: center;
-      }
-    }
-  }
-}

+ 0 - 441
pc/src/pages/A2Main/GoodsSw/index.tsx

@@ -1,441 +0,0 @@
-import React, {
-  useCallback,
-  useEffect,
-  useMemo,
-  useRef,
-  useState,
-} from "react";
-import styles from "./index.module.scss";
-import { useDispatch, useSelector } from "react-redux";
-import { A2_APIgetGoodsList, A2_APIgetSelectData } from "@/store/action/A2Main";
-import { A2GoodsType, A2getGoodsDataType } from "@/types";
-import { RootState } from "@/store";
-import ImageLazy from "@/components/ImageLazy";
-import { Input, Select } from "antd";
-import classNames from "classnames";
-import GoodsInfo from "../GoodsInfo";
-import { CloseOutlined } from "@ant-design/icons";
-import curImg from "@/assets/img/goods/cur.png";
-import curAcImg from "@/assets/img/goods/curAc.png";
-
-function GoodsSw() {
-  // 滚轮提示
-  const [curTit, setCurTit] = useState(true);
-
-  const curTimeRef = useRef(0);
-  const [curCut, setCurCut] = useState(true);
-
-  useEffect(() => {
-    if (!curTit) {
-      localStorage.setItem("YPZZ_CUR", "1");
-      clearInterval(curTimeRef.current);
-    }
-  }, [curTit]);
-
-  useEffect(() => {
-    // 开启滚轮提示 图片更换 定时器
-    clearInterval(curTimeRef.current);
-    curTimeRef.current = window.setInterval(() => {
-      setCurCut(!curCut);
-    }, 2000);
-  }, [curCut]);
-
-  useEffect(() => {
-    const isFlag = localStorage.getItem("YPZZ_CUR");
-    if (isFlag) setCurTit(false);
-  }, []);
-
-  const dispatch = useDispatch();
-
-  useEffect(() => {
-    // 发送请求拿到下拉框数据
-    dispatch(A2_APIgetSelectData("age"));
-    dispatch(A2_APIgetSelectData("texture"));
-  }, [dispatch]);
-
-  // 获取下拉数据
-  const selectData = useSelector((state: RootState) => state.A2Main.selectData);
-
-  // 第一次不显示暂无信息
-  const [flagOne, setFlagOne] = useState(false);
-
-  useEffect(() => {
-    window.setTimeout(() => {
-      setFlagOne(true);
-    }, 500);
-  }, []);
-
-  // 发送请求函数
-  const [getData, setGetData] = useState<A2getGoodsDataType>({
-    dictAge: "",
-    dictTexture: "",
-    searchKey: "",
-    pageNum: 1,
-    pageSize: 9999,
-  });
-
-  const getListFu = useCallback(async () => {
-    await dispatch(A2_APIgetGoodsList(getData));
-  }, [dispatch, getData]);
-
-  // 从仓库获取数据
-  const goodsListAll = useSelector(
-    (state: RootState) => state.A2Main.goodsList
-  );
-
-  // 分为上下2个模块
-  const list1 = useMemo(() => {
-    const arr = [] as A2GoodsType[];
-    goodsListAll.forEach((v, i) => {
-      if (i % 2 === 0) arr.push(v);
-    });
-    if (arr.length > 4) {
-      for (let i = 0; i < 4; i++) {
-        arr.push(arr[i]);
-      }
-    }
-    return arr;
-  }, [goodsListAll]);
-
-  // 下面的数组
-  const list2 = useMemo(() => {
-    const arr = [] as A2GoodsType[];
-    goodsListAll.forEach((v, i) => {
-      if (i % 2 !== 0) arr.push(v);
-    });
-    if (arr.length > 4) {
-      for (let i = 0; i < 4; i++) {
-        arr.push(arr[i]);
-      }
-    }
-    return arr;
-  }, [goodsListAll]);
-
-  useEffect(() => {
-    // 发送请求
-    getListFu();
-  }, [getListFu]);
-
-  // 名称的输入
-  const nameTime = useRef(-1);
-  const nameChange = useCallback(
-    (e: React.ChangeEvent<HTMLInputElement>) => {
-      clearTimeout(nameTime.current);
-      nameTime.current = window.setTimeout(() => {
-        setGetData({
-          ...getData,
-          searchKey: e.target.value,
-        });
-      }, 500);
-    },
-    [getData]
-  );
-
-  // -----点击了单个藏品打开的页面----------
-  const [open, setOpen] = useState(false);
-  const openRef = useRef(0);
-
-  // 第一个盒子的总宽度
-  const goddsSw1 = useMemo(() => {
-    return window.innerWidth * 0.25 * list1.length;
-  }, [list1.length]);
-
-  // 4个定时器
-  const timeS1 = useRef(-1);
-  const timeS2 = useRef(-1);
-  const time1 = useRef(-1);
-  const time2 = useRef(-1);
-
-  // 上面的开始自动滚动
-  const scroolFu1 = useCallback(
-    (dom: HTMLDivElement, num: number, time: number) => {
-      clearTimeout(timeS1.current);
-      timeS1.current = window.setTimeout(() => {
-        clearInterval(time1.current);
-        let numAuto = num;
-        time1.current = window.setInterval(() => {
-          numAuto += 1;
-
-          if (dom.scrollLeft + dom.clientWidth >= dom.scrollWidth) {
-            numAuto = 0;
-          }
-          dom.scrollLeft = numAuto;
-        }, 20);
-      }, time);
-    },
-    []
-  );
-
-  // 清理第一个定时器
-  const colseTime1 = useCallback(() => {
-    clearTimeout(timeS1.current);
-    clearInterval(time1.current);
-    const dom = document.querySelector("#goddsSwBox1") as HTMLDivElement;
-    if (dom && list1.length > 4 && !open) {
-      scroolFu1(dom, dom.scrollLeft, 3000);
-    }
-  }, [list1, open, scroolFu1]);
-
-  // 下面的开始自动滚动
-  const scroolFu2 = useCallback(
-    (dom: HTMLDivElement, num: number, time: number) => {
-      clearTimeout(timeS2.current);
-      timeS2.current = window.setTimeout(() => {
-        clearInterval(time2.current);
-        let numAuto = num;
-        dom.scrollLeft = numAuto;
-        time2.current = window.setInterval(() => {
-          numAuto -= 1;
-          if (numAuto <= 0) {
-            numAuto = dom.scrollWidth - dom.clientWidth;
-          }
-          dom.scrollLeft = numAuto;
-        }, 20);
-      }, time);
-    },
-    []
-  );
-
-  // 清理第二个定时器
-  const closeTime2 = useCallback(() => {
-    clearTimeout(timeS2.current);
-    clearInterval(time2.current);
-    const dom = document.querySelector("#goddsSwBox2") as HTMLDivElement;
-    if (dom && list2.length > 4 && !open) {
-      scroolFu2(dom, dom.scrollLeft, 3000);
-    }
-  }, [list2, open, scroolFu2]);
-
-  // 上面的数组改变了数据
-  useEffect(() => {
-    if (list1.length > 4) {
-      const dom = document.querySelector("#goddsSwBox1") as HTMLDivElement;
-      // 监听鼠标滚轮
-      dom.onwheel = (e) => {
-        // 使用过滚轮
-        setCurTit(false);
-
-        e.preventDefault();
-        const num = dom.scrollLeft;
-        if (dom.scrollLeft + dom.clientWidth >= dom.scrollWidth)
-          dom.scrollLeft = 0;
-        // else if (num <= 0) dom.scrollLeft = dom.scrollWidth - dom.clientWidth;
-        else dom.scrollLeft = num + e.deltaY;
-        colseTime1();
-      };
-      // 开启定时器
-      scroolFu1(dom, 0, 1000);
-    } else colseTime1();
-  }, [colseTime1, list1, scroolFu1]);
-
-  // 下面的数组改变了数据
-  useEffect(() => {
-    if (list2.length > 4) {
-      const dom = document.querySelector("#goddsSwBox2") as HTMLDivElement;
-      // 初始滚动到末尾
-      dom.scrollLeft = dom.scrollWidth - dom.clientWidth;
-      // 监听鼠标滚轮
-      dom.onwheel = (e) => {
-        // 使用过滚轮
-        setCurTit(false);
-
-        e.preventDefault();
-        const num = dom.scrollLeft;
-        if (num <= 0) dom.scrollLeft = dom.scrollWidth - dom.clientWidth;
-        // else if (dom.scrollLeft + dom.clientWidth >= dom.scrollWidth)
-        //   dom.scrollLeft = 0;
-        else dom.scrollLeft = num + e.deltaY;
-
-        closeTime2();
-      };
-      // 开启定时器
-      scroolFu2(dom, dom.scrollWidth - dom.clientWidth, 1000);
-    } else closeTime2();
-  }, [closeTime2, list2, scroolFu2]);
-
-  // 第二个盒子的总宽度
-  const goddsSw2 = useMemo(() => {
-    return window.innerWidth * 0.25 * list2.length;
-  }, [list2.length]);
-
-  // 点击藏品
-  const clickGoodFu = useCallback((id: number) => {
-    openRef.current = id;
-
-    setOpen(true);
-
-    // console.log(123, id);
-  }, []);
-
-  // 打开了单个文物详情页,关闭之后的逻辑
-  useEffect(() => {
-    if (open) {
-      clearTimeout(timeS1.current);
-      clearInterval(time1.current);
-      clearTimeout(timeS2.current);
-      clearInterval(time2.current);
-    } else if (openRef.current) {
-      const dom1 = document.querySelector("#goddsSwBox1") as HTMLDivElement;
-      const dom2 = document.querySelector("#goddsSwBox2") as HTMLDivElement;
-      scroolFu1(dom1, dom1.scrollLeft, 3000);
-      scroolFu2(dom2, dom2.scrollLeft, 3000);
-    }
-  }, [open, scroolFu1, scroolFu2]);
-
-  // 离开页面的时候清理4个定时器
-  useEffect(() => {
-    return () => {
-      clearTimeout(timeS1.current);
-      clearTimeout(timeS2.current);
-      clearInterval(time1.current);
-      clearInterval(time2.current);
-      // 清理 滚轮提示 定时器
-      clearInterval(curTimeRef.current);
-    };
-  }, []);
-
-  const curTime = useRef(-1);
-
-  useEffect(() => {
-    clearTimeout(curTime.current);
-    curTime.current = window.setTimeout(() => {
-      const dom = document.querySelector(".curTitBox") as HTMLDivElement;
-      if (list1.length > 4) {
-        if (dom) {
-          dom.style.opacity = "1";
-          dom.style.pointerEvents = "auto";
-        }
-      }
-    }, 500);
-    return () => {
-      clearTimeout(curTime.current);
-    };
-  }, [list1.length]);
-
-  return (
-    <div className={styles.GoodsSw}>
-      {/* 轮播图主体 */}
-
-      {goodsListAll.length <= 0 ? (
-        <div className="noInfo" hidden={!flagOne}>
-          暂无更多内容
-        </div>
-      ) : (
-        <div className="goddsBox">
-          {/* 第一个自动播发的盒子 */}
-          <div
-            id="goddsSwBox1"
-            className="goddsSwBox"
-            onClick={() => colseTime1()}
-            // onMouseLeave={() => auto1Fu()}
-          >
-            <div className="goddsSw" style={{ width: goddsSw1 + "px" }}>
-              {list1.map((v, i) => (
-                <div key={i} className="goddsRow" title={v.name}>
-                  <div className="name">
-                    {v.name.length > 10
-                      ? v.name.substring(0, 10) + "..."
-                      : v.name}
-                  </div>
-                  <div className="goddsImg" onClick={() => clickGoodFu(v.id)}>
-                    <ImageLazy
-                      src={v.thumb}
-                      width="100%"
-                      height="100%"
-                      noLook
-                    />
-                  </div>
-                </div>
-              ))}
-            </div>
-          </div>
-          {/* 第二个自动播放的盒子 */}
-          <div
-            id="goddsSwBox2"
-            className="goddsSwBox goddsSwBox2"
-            onClick={() => closeTime2()}
-            // onMouseLeave={() => auto2Fu()}
-          >
-            <div className="goddsSw" style={{ width: goddsSw2 + "px" }}>
-              {list2.map((v, i) => (
-                <div key={i} className="goddsRow" title={v.name}>
-                  <div className="name">
-                    {v.name.length > 10
-                      ? v.name.substring(0, 10) + "..."
-                      : v.name}
-                  </div>
-                  <div className="goddsImg" onClick={() => clickGoodFu(v.id)}>
-                    <ImageLazy
-                      src={v.thumb}
-                      width="100%"
-                      height="100%"
-                      noLook
-                    />
-                  </div>
-                </div>
-              ))}
-            </div>
-          </div>
-        </div>
-      )}
-
-      {/* 下面的筛选框 */}
-      <div className="searchBox">
-        <div className="searRow">
-          <Select
-            placeholder="种类"
-            style={{ width: 150 }}
-            options={selectData["texture"]}
-            onChange={(e) => setGetData({ ...getData, dictTexture: e })}
-          />
-        </div>
-        <div className="searRow">
-          <Select
-            placeholder="年代"
-            style={{ width: 150 }}
-            options={selectData["age"]}
-            onChange={(e) => setGetData({ ...getData, dictAge: e })}
-          />
-        </div>
-        <div className="searRow">
-          <Input
-            maxLength={25}
-            style={{ width: 220 }}
-            placeholder="请输入关键词"
-            allowClear
-            onChange={(e) => nameChange(e)}
-          />
-        </div>
-      </div>
-
-      {/* 单个藏品详情盒子 */}
-      <div className={classNames("goodsInfoBox", open ? "goodsInfoBoxAc" : "")}>
-        {open ? (
-          <GoodsInfo
-            isOpen={false}
-            id={openRef.current}
-            closePage={() => setOpen(false)}
-          />
-        ) : null}
-      </div>
-
-      {/* 滚轮提示 */}
-      {curTit ? (
-        <div className="curTitBox" hidden={open}>
-          <div className="curClose" onClick={() => setCurTit(false)}>
-            <CloseOutlined />
-          </div>
-          <div className="curImg">
-            <img src={curImg} alt="" style={{ opacity: curCut ? 1 : 0 }} />
-            <img src={curAcImg} alt="" style={{ opacity: curCut ? 0 : 1 }} />
-          </div>
-          <p>鼠标滚轮可控制图片滚动</p>
-        </div>
-      ) : null}
-    </div>
-  );
-}
-
-const MemoGoodsSw = React.memo(GoodsSw);
-
-export default MemoGoodsSw;

+ 238 - 0
pc/src/pages/A2Main/Tab4/index.module.scss

@@ -0,0 +1,238 @@
+.Tab4 {
+  width: 100%;
+  height: 100%;
+  background-size: 100% 100%;
+  padding: 0 60px;
+  position: relative;
+
+  :global {
+    .tab4Top {
+      display: flex;
+      justify-content: center;
+      height: 70px;
+      align-items: center;
+
+      .tab4Top1 {
+        cursor: pointer;
+        margin-right: 30px;
+        width: 152px;
+        height: 40px;
+        text-align: center;
+        line-height: 38px;
+        align-items: center;
+        border-radius: 0 10px 0 10px;
+        border: 1px solid var(--themeColor);
+        color: var(--themeColor);
+      }
+
+      .tab4Top1Ac {
+        background-color: var(--themeColor);
+        color: #47392C;
+      }
+
+      .tab4Top2 {
+        width: 425px;
+        height: 40px;
+        display: flex;
+        border: 1px solid var(--themeColor);
+        border-radius: 0 10px 0 10px;
+        color: var(--themeColor);
+
+        .tab4Top2_1 {
+          width: 60px;
+          height: 100%;
+          font-size: 24px;
+          text-align: center;
+          line-height: 38px;
+
+        }
+
+        .ant-input {
+          background-color: transparent;
+          border: none;
+          color: var(--themeColor);
+
+          &::-webkit-input-placeholder {
+            /* WebKit browsers */
+            color: var(--themeColor);
+            opacity: .6;
+          }
+
+          &:-moz-placeholder {
+            /* Mozilla Firefox 4 to 18 */
+            color: var(--themeColor);
+            opacity: .6;
+          }
+
+          &::-moz-placeholder {
+            /* Mozilla Firefox 19+ */
+            color: var(--themeColor);
+            opacity: .6;
+          }
+
+          &:-ms-input-placeholder {
+            /* Internet Explorer 10+ */
+            color: var(--themeColor);
+            opacity: .6;
+          }
+        }
+
+        .tab4Top2_2 {
+          cursor: pointer;
+          width: 100px;
+          height: 100%;
+          text-align: center;
+          line-height: 38px;
+          position: relative;
+
+          &::before {
+            content: '';
+            width: 1px;
+            height: 30px;
+            z-index: 10;
+            top: 5px;
+            left: 0;
+            position: absolute;
+            background: linear-gradient(rgba(240, 216, 156, 0), rgba(240, 216, 156, 1), rgba(240, 216, 156, 0));
+          }
+
+        }
+      }
+    }
+
+    .tab4Top2 {
+      margin: 10px 0 15px;
+      width: 100%;
+      height: 36px;
+      overflow-x: auto;
+
+      .appSw {
+        cursor: move;
+        height: 100%;
+
+        .swiper-slide {
+          width: auto !important;
+
+          .row {
+            padding: 0 15px;
+            cursor: pointer;
+            font-size: 16px;
+            color: #fff;
+          }
+
+          .active {
+            pointer-events: none;
+            color: var(--themeColor);
+            position: relative;
+
+            &::before {
+              content: '';
+              position: absolute;
+              bottom: -10px;
+              left: 0;
+              width: 100%;
+              height: 2px;
+              background-color: var(--themeColor);
+            }
+          }
+        }
+      }
+    }
+
+    .tav4MainNone {
+      width: 100%;
+      height: calc(100% - 200px);
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      padding-bottom: 100px;
+      color: var(--themeColor);
+      font-size: 30px;
+      letter-spacing: 4px;
+    }
+
+    .tab4Main {
+      width: 100%;
+      height: calc(100% - 200px);
+      display: flex;
+      flex-wrap: wrap;
+
+      .tab4Mrow {
+        transition: all .2s;
+        cursor: pointer;
+        width: 23.5%;
+        height: 46%;
+        margin-right: 2%;
+        margin-bottom: 2%;
+        background-color: #fff;
+        padding: 10px;
+        border-radius: 6px;
+
+
+        &:nth-of-type(4n) {
+          margin-right: 0;
+        }
+
+        .tab4MrowImg {
+          width: 100%;
+          height: calc(100% - 40px);
+
+          .adm-image {
+            img {
+              object-fit: contain !important;
+            }
+          }
+        }
+
+        &>p {
+          text-align: center;
+          height: 40px;
+          line-height: 45px;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          color: #47392C;
+          font-size: 16px;
+        }
+        &:hover{
+          box-shadow: 1px 1px 5px 5px;
+        }
+      }
+
+
+    }
+
+    // 分页
+    .tab4Page {
+      display: flex;
+      justify-content: center;
+
+      .ant-pagination-prev button,
+      .ant-pagination-next button {
+        color: var(--themeColor);
+      }
+
+      .ant-pagination-item-ellipsis {
+        color: var(--themeColor) !important;
+      }
+
+      .ant-pagination-item-active {
+        background-color: var(--themeColor);
+
+        a {
+          color: #47392C !important;
+        }
+      }
+
+      .ant-pagination-options {
+        color: var(--themeColor);
+
+        input {
+          background-color: transparent;
+          border: 1px solid var(--themeColor);
+          color: var(--themeColor);
+        }
+      }
+    }
+  }
+}

+ 205 - 0
pc/src/pages/A2Main/Tab4/index.tsx

@@ -0,0 +1,205 @@
+import React, { useCallback, useEffect, useRef, useState } from "react";
+import styles from "./index.module.scss";
+import classNames from "classnames";
+
+import { A2getGoodsDataType } from "@/types";
+import { Input, Pagination } from "antd";
+
+import { SearchOutlined } from "@ant-design/icons";
+import { useDispatch, useSelector } from "react-redux";
+import { A2_APIgetGoodsList, A2_APIgetSelectData } from "@/store/action/A2Main";
+import { RootState } from "@/store";
+import { envUrl } from "@/utils/env";
+import ImageLazy from "@/components/ImageLazy";
+
+// 轮播图
+import { Swiper, SwiperSlide } from "swiper/react";
+import { FreeMode } from "swiper";
+// Import Swiper styles
+import "swiper/css";
+import "swiper/css/free-mode";
+import Tab4Info from "../Tab4Info";
+
+const typeArr = [
+  { id: "", name: "二维文物" },
+  { id: "model", name: "三维文物" },
+];
+
+function Tab4() {
+  const dispatch = useDispatch();
+
+  // 看看是不是还没有发送请求
+  const [isDataFlag, setIsDataFlag] = useState(false);
+
+  // 发送请求参数
+  const [getData, setGetData] = useState<A2getGoodsDataType>({
+    dictAge: "",
+    dictTexture: "",
+    searchKey: "",
+    pageNum: 1,
+    pageSize: 8,
+    type: "",
+  });
+
+  // 发送请求函数
+  const getList = useCallback(() => {
+    setIsDataFlag(true);
+
+    let searchKey = "";
+    if (inpValueRef.current) searchKey = inpValueRef.current.input.value;
+    dispatch(A2_APIgetGoodsList({ ...getData, searchKey }));
+  }, [dispatch, getData]);
+
+  useEffect(() => {
+    getList();
+  }, [getList]);
+
+  // 输入框
+  const [inpValue, setInpValue] = useState("");
+
+  const inpValueRef = useRef<any>(null);
+
+  useEffect(() => {
+    inpValueRef.current = inpValue;
+  }, [inpValue]);
+
+  useEffect(() => {
+    // 发送请求拿到下拉框数据
+    // dispatch(A2_APIgetSelectData("age"));
+    dispatch(A2_APIgetSelectData("texture"));
+  }, [dispatch]);
+
+  // 获取下拉数据
+  const selectData = useSelector(
+    (state: RootState) => state.A2Main.selectData.texture
+  );
+
+  // 从仓库获取数据
+  const goodsList = useSelector((state: RootState) => state.A2Main.goodsList);
+
+  // 详情页 id
+  const [infoId, setInfoId] = useState(0);
+
+  return (
+    <div
+      className={styles.Tab4}
+      style={{ backgroundImage: `url(${envUrl}/goods/bac.jpg)` }}
+    >
+      <div className="tab4Top">
+        {/* 二维 三维的筛选 */}
+        {typeArr.map((v) => (
+          <div
+            key={v.id}
+            className={classNames(
+              "tab4Top1",
+              v.id === getData.type ? "tab4Top1Ac" : ""
+            )}
+            onClick={() => setGetData({ ...getData, type: v.id, pageNum: 1 })}
+          >
+            {v.name}
+          </div>
+        ))}
+
+        {/* 输入框 */}
+        <div className="tab4Top2">
+          <div className="tab4Top2_1">
+            <SearchOutlined />
+          </div>
+          <Input
+            placeholder="请输入关键词"
+            maxLength={30}
+            value={inpValue}
+            onChange={(e) => setInpValue(e.target.value.trim())}
+            ref={inpValueRef}
+          />
+          <div
+            className="tab4Top2_2"
+            onClick={() => {
+              if (getData.pageNum === 1) getList();
+              else setGetData({ ...getData, pageNum: 1 });
+            }}
+          >
+            搜索
+          </div>
+        </div>
+      </div>
+
+      {/* 类型的筛选 */}
+      <div className="tab4Top2">
+        <Swiper
+          modules={[FreeMode]}
+          className="appSw"
+          spaceBetween={0}
+          slidesPerView="auto"
+          freeMode={true}
+          mousewheel={true}
+          // onSlideChange={(e) => console.log("slide change", e)}
+          // onSwiper={(swiper) => (mySwiperRef.current = swiper)}
+        >
+          {selectData.map((v) => (
+            <SwiperSlide key={v.label}>
+              <div
+                onClick={(e) =>
+                  setGetData({
+                    ...getData,
+                    dictTexture: v.value as string,
+                    pageNum: 1,
+                  })
+                }
+                className={classNames(
+                  "row",
+                  getData.dictTexture === v.value ? "active" : ""
+                )}
+              >
+                <span>{v.label}</span>
+              </div>
+            </SwiperSlide>
+          ))}
+        </Swiper>
+      </div>
+
+      {/* 主要内容 */}
+      {goodsList.list.length <= 0 && isDataFlag ? (
+        <div className="tav4MainNone">暂无数据</div>
+      ) : (
+        <div className="tab4Main">
+          {goodsList.list.map((v) => (
+            <div
+              className="tab4Mrow"
+              key={v.id}
+              title={v.name}
+              onClick={() => setInfoId(v.id)}
+            >
+              <div className="tab4MrowImg">
+                <ImageLazy src={v.thumb} noLook width="100%" height="100%" />
+              </div>
+              <p>{v.name}</p>
+            </div>
+          ))}
+        </div>
+      )}
+
+      {/* 分页器 */}
+      <div className="tab4Page">
+        <Pagination
+          showQuickJumper
+          current={getData.pageNum}
+          total={goodsList.total}
+          pageSize={15}
+          hideOnSinglePage={true}
+          onChange={(page) => setGetData({ ...getData, pageNum: page })}
+          showSizeChanger={false}
+        />
+      </div>
+
+      {/* 点击文物进入详情页 */}
+      {infoId ? (
+        <Tab4Info id={infoId} closePage={() => setInfoId(0)} isOpen={false} />
+      ) : null}
+    </div>
+  );
+}
+
+const MemoTab4 = React.memo(Tab4);
+
+export default MemoTab4;

+ 166 - 0
pc/src/pages/A2Main/Tab4Info/index.module.scss

@@ -0,0 +1,166 @@
+.Tab4Info {
+  position: absolute;
+  z-index: 100;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background-size: 100% 100%;
+
+  :global {
+    .t4ItoBack {
+      cursor: pointer;
+      position: absolute;
+      z-index: 10;
+      top: 30px;
+      left: 36px;
+    }
+
+    // 顶部名字
+    .topName {
+      position: absolute;
+      z-index: 10;
+      left: 50%;
+      transform: translateX(-50%);
+      top: 40px;
+      font-weight: 700;
+      font-size: 24px;
+      color: var(--themeColor);
+      letter-spacing: 4px;
+    }
+
+    // 顶部按钮
+    .R_typeCutBox {
+      position: absolute;
+      z-index: 10;
+      left: 50%;
+      transform: translateX(-50%);
+      top: 86px;
+      height: 36px;
+      display: flex;
+
+      .R_typeCutRow {
+        margin: 0 10px;
+        cursor: pointer;
+        color: var(--themeColor);
+        line-height: 36px;
+        text-align: center;
+        height: 36px;
+        padding: 0 30px;
+        border-radius: 0 10px 0 10px;
+        border: 1px solid var(--themeColor);
+      }
+
+      .R_typeCutRowAc {
+        background-color: var(--themeColor);
+        color: #4A403D;
+      }
+    }
+
+    // 主体模型
+    .t4IifrBox {
+      position: absolute;
+      top: 0;
+      left: 0;
+      width: 100%;
+      height: 100%;
+
+      iframe {
+        width: 100%;
+        height: 100%;
+      }
+    }
+
+    // 其他附件
+    .t4IFileBox {
+      width: 1252px;
+      height: calc(100% - 230px);
+      position: absolute;
+      left: 50%;
+      top: 140px;
+      transform: translateX(-50%);
+      z-index: 10;
+
+      .R1_row {
+        width: 100%;
+        height: 100%;
+        text-align: center;
+        position: absolute;
+        top: 0;
+        left: 0;
+        opacity: 0;
+        pointer-events: none;
+
+        video {
+          max-width: 100%;
+          max-height: 100%;
+        }
+      }
+
+      .R1_rowAc {
+        opacity: 1;
+        pointer-events: auto;
+      }
+
+      .showIndBox {
+        position: absolute;
+        z-index: 10;
+        bottom: 10px;
+        left: 50%;
+        transform: translateX(-50%);
+        font-size: 16px;
+        color: #4A403D;
+        background-color: var(--themeColor);
+        padding: 5px 10px;
+        border-radius: 20px;
+      }
+    }
+
+    // 左右按钮
+    .R_left {
+      cursor: pointer;
+      position: absolute;
+      top: 50%;
+      width: 50px;
+      height: 50px;
+      left: 30px;
+      z-index: 12;
+      transform: translateY(-50%);
+      display: flex;
+      justify-content: center;
+      align-items: center;
+    }
+
+    .R_right {
+      cursor: pointer;
+      position: absolute;
+      top: 50%;
+      width: 50px;
+      height: 50px;
+      right: 30px;
+      z-index: 12;
+      transform: translateY(-50%);
+      display: flex;
+      justify-content: center;
+      align-items: center;
+    }
+
+    .R_arrowNo {
+      opacity: .5;
+      pointer-events: none;
+    }
+
+    // 底部文字集合
+    .t4ITxts {
+      position: absolute;
+      padding: 0 10px;
+      text-align: center;
+      z-index: 10;
+      bottom: 5px;
+      left: 0;
+      width: 100%;
+      height: 80px;
+    }
+
+  }
+}

+ 399 - 0
pc/src/pages/A2Main/Tab4Info/index.tsx

@@ -0,0 +1,399 @@
+/* eslint-disable jsx-a11y/iframe-has-title */
+import React, {
+  useCallback,
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+} from "react";
+import styles from "./index.module.scss";
+import toBackImg from "@/assets/img/goods/toBack.png";
+import { envUrl } from "@/utils/env";
+import {
+  A2BarrageType,
+  A2FileObjType,
+  A2FileType,
+  A2GoodsType,
+  A2QuestionType,
+} from "@/types";
+import {
+  A2_APIgetBarrage,
+  A2_APIgetBarrageAll,
+  A2_APIgetConfigBarrage,
+  A2_APIgetGoodsInfo,
+  A2_APIgetQuestion,
+  A2_APIgoodsaddStar,
+} from "@/store/action/A2Main";
+import { MessageFu } from "@/utils/message";
+import classNames from "classnames";
+import { baseURL } from "@/utils/http";
+import ImageLazy from "@/components/ImageLazy";
+import R_leftImg from "@/assets/img/goods/R_left.png";
+import R_rightImg from "@/assets/img/goods/R_right.png";
+
+type Props = {
+  isOpen: boolean;
+  id: number;
+  closePage?: () => void;
+};
+
+function Tab4Info({ isOpen, id, closePage }: Props) {
+  // 文物信息
+  const [info, setInfo] = useState<A2GoodsType>({} as A2GoodsType);
+
+  // 附件数据(除开音频)
+  const [fileList, setFileList] = useState<A2FileObjType>({
+    model: [],
+    video: [],
+    img: [],
+  });
+
+  // ---------------右侧图标
+
+  // 音频
+  const [right1, setRight1] = useState({ show: false, url: "" });
+
+  // 留言板(默认显示),传递 doneIn 到二级页面 看看是否开启了  留言到后端的  功能
+  const [right2, setRight2] = useState({ done: true, doneIn: false });
+
+  //问答
+  const [right3, setRight3] = useState(false);
+
+  // 知识
+  const [right4, setRight4] = useState(false);
+
+  // 弹幕
+  const [right5, setRight5] = useState({ show: false, done: false });
+
+  // 点赞
+  const [right6, setRight6] = useState(false);
+  // 分享
+  const [right7, setRight7] = useState(false);
+
+  // 点击点赞
+  const likeClickFu = useCallback(async () => {
+    if (right6) return;
+    setRight6(true);
+    try {
+      await A2_APIgoodsaddStar(id);
+    } catch (error) {
+      console.log(error);
+    }
+    window.setTimeout(() => {
+      setRight6(false);
+    }, 3000);
+  }, [id, right6]);
+
+  // 点击分享链接
+  const fenXClickFu = useCallback(() => {
+    if (right7) return;
+    setRight7(true);
+    window.setTimeout(() => {
+      setRight7(false);
+    }, 3000);
+    let OrderNumber = window.location.origin + "/pc/#/goods?id=" + id;
+    let newInput = document.createElement("input");
+    newInput.value = OrderNumber;
+    document.body.appendChild(newInput);
+    newInput.select();
+    document.execCommand("Copy");
+    newInput.remove();
+    MessageFu.success("复制链接成功");
+  }, [id, right7]);
+
+  // 留言-知识-问答 弹窗的选中状态(打开)
+  const [leftAc, setLeftAc] = useState(1);
+
+  // 问答数组
+  const [question, setQuestion] = useState<A2QuestionType[]>([]);
+
+  // 文物留言的数组
+  const [barrage, setBarrage] = useState<A2BarrageType[]>([]);
+
+  // 所有弹幕的数组
+  const [barrageAll, setBarrageAll] = useState<A2BarrageType[]>([]);
+  const barrMoveRef = useRef<HTMLDivElement>(null);
+  const [barrInd, setBarrInd] = useState(0);
+  const barrMoveRefKill = useRef<any>(null);
+
+  // 每次弹幕的索引变化的时候
+  useEffect(() => {
+    window.setTimeout(() => {
+      const width = barrMoveRef.current?.offsetWidth || 0;
+
+      if (barrMoveRef.current) {
+        barrMoveRef.current.style.right = -width - 200 + "px";
+
+        const endNum = -window.innerWidth - width - 200;
+        barrMoveRefKill.current?.kill();
+        // 开始动画
+
+        // 总弹幕数量只有 1  的情况
+        if (barrageAll.length === 1) {
+          barrMoveRefKill.current = gsap.to(barrMoveRef.current, {
+            duration: 16,
+            ease: "none",
+            x: endNum,
+            repeat: -1,
+          });
+        } else if (barrageAll.length > 1) {
+          // 有超过 1 的情况
+          barrMoveRefKill.current = gsap.fromTo(
+            barrMoveRef.current,
+            { x: 0 },
+            {
+              duration: 16,
+              ease: "none",
+              x: endNum,
+              onComplete: () => {
+                let num = barrInd + 1;
+                if (num >= barrageAll.length) num = 0;
+                setBarrInd(num);
+              },
+            }
+          );
+        }
+      }
+    }, 200);
+  }, [barrInd, barrageAll.length]);
+
+  // 通过id获取详情
+  const getDataFu = useCallback(
+    async (id: number) => {
+      const res = await A2_APIgetGoodsInfo(id);
+      if (res.code === 0) {
+        const info: A2GoodsType = res.data.entity;
+
+        // 留言板 和 弹幕开关 是否显示
+        const res_b = await A2_APIgetConfigBarrage();
+        if (res_b.code === 0) {
+          const value_b = JSON.parse(res_b.data.content);
+          if (value_b.value) {
+            // 获取所有的弹幕数组
+            const resBa_all = await A2_APIgetBarrageAll();
+            if (resBa_all.code === 0) {
+              setBarrageAll(resBa_all.data);
+            }
+            //打开了弹幕总开关 并且所有弹幕的数组长度>0
+            if (resBa_all.data.length) {
+              // 显示弹幕开关
+              setRight5({ show: true, done: true });
+            }
+
+            // 文物的弹幕留言开关 和总 弹幕开关都开启了
+            if (info.isBarrage) setRight2({ done: true, doneIn: true });
+          }
+        }
+
+        const file: A2FileType[] = res.data.file;
+
+        // 整理附件数据
+        const fileObj: A2FileObjType = {
+          model: [],
+          video: [],
+          img: [],
+        };
+        file.forEach((v) => {
+          if (v.type === "model") fileObj.model.push(v);
+          else if (v.type === "video") fileObj.video.push(v);
+          else if (v.type === "img") fileObj.img.push(v);
+        });
+
+        setFileList(fileObj);
+
+        // 有上传音频
+        const isAudioObj = file.find((v) => v.type === "audio");
+        if (isAudioObj) {
+          setRight1({ show: isOpen ? true : false, url: isAudioObj.filePath });
+        }
+
+        setInfo(info);
+
+        // 看看是否有相关的问答
+        const res2 = await A2_APIgetQuestion(id);
+        if (res2.code === 0) {
+          // 如有有选择 知识驿站
+          if (info.tagType) setRight4(true);
+          // 如果有问答
+          if (res2.data.length) setRight3(true);
+          const res3 = await A2_APIgetBarrage(id);
+          setQuestion(res2.data);
+          if (res3.code === 0) {
+            // 如果这条文物有留言
+            // if (res3.data.length) setRight2;
+            setBarrage(res3.data);
+          }
+        }
+      }
+    },
+    [isOpen]
+  );
+
+  useEffect(() => {
+    getDataFu(id);
+    return () => {
+      barrMoveRefKill.current?.kill();
+    };
+  }, [getDataFu, id]);
+
+  //  文件类型 type
+  const [type, setType] = useState<"model" | "video" | "img">("model");
+
+  // 每次变化type的时候把 索引变成0
+  useEffect(() => {
+    setShowInd(0);
+  }, [type]);
+
+  // 切换不同文件(模型/视频/图片的数组)
+  const typeArr = useMemo(() => {
+    const arr: {
+      name: "模型" | "视频" | "图片";
+      type: "model" | "video" | "img";
+    }[] = [];
+    if (fileList.model.length) arr.push({ name: "模型", type: "model" });
+    if (fileList.video.length) arr.push({ name: "视频", type: "video" });
+    if (fileList.img.length) arr.push({ name: "图片", type: "img" });
+    return arr;
+  }, [fileList]);
+
+  // 在页面展示的数组
+  const list = useMemo(() => {
+    return fileList[type];
+  }, [fileList, type]);
+
+  // 当前显示的 索引
+  const [showInd, setShowInd] = useState(0);
+
+  const cutIndFu = useCallback(
+    (num: number) => {
+      setShowInd(showInd + num);
+    },
+    [showInd]
+  );
+
+  // 底部的 文字展示信息集合
+  const tstS = useMemo(() => {
+    let txt = "";
+    if (info.dictTexture)
+      txt += (
+        <>
+          <span>类别:</span>
+          {info.dictTexture}&emsp;
+        </>
+      );
+    if (info.dictAge)
+      txt += (
+        <>
+          <span>年代:</span>
+          {info.dictAge}&emsp;
+        </>
+      );
+    if (info.dictLevel)
+      txt += (
+        <>
+          <span>级别:</span>
+          {info.dictLevel}&emsp;
+        </>
+      );
+    if (info.description)
+      txt += (
+        <>
+          <span>简介:</span>
+          {info.description}&emsp;
+        </>
+      );
+    console.log(132, txt);
+
+    return txt;
+  }, [info.description, info.dictAge, info.dictLevel, info.dictTexture]);
+
+  return (
+    <div
+      className={styles.Tab4Info}
+      style={{ backgroundImage: `url(${envUrl}/goods/bac.jpg)` }}
+    >
+      {/* 返回按钮 */}
+      <div className="t4ItoBack" onClick={closePage}>
+        <img src={toBackImg} alt="" />
+      </div>
+
+      {/* 顶部名称 */}
+      <div className="topName">{info.name}</div>
+
+      {/* 顶部tab */}
+      <div className="R_typeCutBox" hidden={typeArr.length <= 1}>
+        {typeArr.map((v) => (
+          <div
+            onClick={() => setType(v.type)}
+            className={classNames(
+              "R_typeCutRow",
+              type === v.type ? "R_typeCutRowAc" : ""
+            )}
+            key={v.type}
+          >
+            {v.name}
+            {fileList[v.type].length > 1 ? fileList[v.type].length : null}
+          </div>
+        ))}
+      </div>
+
+      {/* 主体模型 */}
+      {fileList.model && fileList.model[0] && fileList.model[0].id ? (
+        <div className="t4IifrBox" hidden={type !== "model"}>
+          <iframe
+            src={`model.html?m=${fileList.model[0].filePath}`}
+            frameBorder="0"
+          ></iframe>
+        </div>
+      ) : null}
+
+      {/* 主体 其他附件 */}
+      <div className="t4IFileBox">
+        {list.map((v, i) => (
+          <div
+            className={classNames("R1_row", i === showInd ? "R1_rowAc" : "")}
+            key={v.id}
+          >
+            {v.type === "video" && i === showInd ? (
+              <video src={baseURL + v.filePath} controls></video>
+            ) : v.type === "img" ? (
+              <ImageLazy src={v.filePath} width="100%" height="100%" />
+            ) : null}
+          </div>
+        ))}
+        {/* 索引 */}
+        {list.length > 1 ? (
+          <div className="showIndBox">
+            {showInd + 1} / {list.length}
+          </div>
+        ) : null}
+      </div>
+
+      {/* 左右按钮 */}
+      <div
+        hidden={list.length <= 1}
+        onClick={() => cutIndFu(-1)}
+        className={classNames("R_left", showInd === 0 ? "R_arrowNo" : "")}
+      >
+        <img src={R_leftImg} alt="" />
+      </div>
+      <div
+        hidden={list.length <= 1}
+        onClick={() => cutIndFu(1)}
+        className={classNames(
+          "R_right",
+          showInd >= list.length - 1 ? "R_arrowNo" : ""
+        )}
+      >
+        <img src={R_rightImg} alt="" />
+      </div>
+
+      {/* 底部文字介绍集合 */}
+      <div className="t4ITxts">{tstS}</div>
+    </div>
+  );
+}
+
+const MemoTab4Info = React.memo(Tab4Info);
+
+export default MemoTab4Info;

+ 0 - 4
pc/src/pages/A2Main/index.module.scss

@@ -152,9 +152,5 @@
         border-radius: 0;
         border-radius: 0;
       }
       }
     }
     }
-
-    .swBox2 {
-      height: 100%;
-    }
   }
   }
 }
 }

+ 9 - 7
pc/src/pages/A2Main/index.tsx

@@ -7,6 +7,7 @@ import history from "@/utils/history";
 import A0Map from "../A0Map";
 import A0Map from "../A0Map";
 import { envData, envDataSonType, envDataType } from "@/utils/env";
 import { envData, envDataSonType, envDataType } from "@/utils/env";
 import Tab1 from "./Tab1";
 import Tab1 from "./Tab1";
+import Tab4 from "./Tab4";
 
 
 function A2Main() {
 function A2Main() {
   // 传给历史
   // 传给历史
@@ -23,7 +24,7 @@ function A2Main() {
     <div className={styles.A2Main}>
     <div className={styles.A2Main}>
       {/* 图片页面 */}
       {/* 图片页面 */}
       <div className="threeBox">
       <div className="threeBox">
-        <A0Map type={type} sonChaneType={(val)=>setType(val)} />
+        <A0Map type={type} sonChaneType={(val) => setType(val)} />
       </div>
       </div>
 
 
       {/* 左上方logo */}
       {/* 左上方logo */}
@@ -34,8 +35,7 @@ function A2Main() {
       <div
       <div
         className={classNames(
         className={classNames(
           "swBox",
           "swBox",
-          type === 1 ? "swBox1" : "",
-          [4, 5].includes(type) ? "swBox2" : ""
+          [1, 4, 5].includes(type) ? "swBox1" : ""
         )}
         )}
       >
       >
         <div className="swBoxMain">
         <div className="swBoxMain">
@@ -61,10 +61,12 @@ function A2Main() {
             ></div>
             ></div>
           </div>
           </div>
           {/* 历史 */}
           {/* 历史 */}
-          {type === 1 ? (
-            <Tab1 data={swData} />
-          ) : type === 4 ? null : type === // <GoodsSw />
-            5 ? null : null // <KnowLedge />
+          {
+            type === 1 ? (
+              <Tab1 data={swData} />
+            ) : type === 4 ? (
+              <Tab4 />
+            ) : type === 5 ? null : null // <KnowLedge />
           }
           }
         </div>
         </div>
       </div>
       </div>

+ 7 - 2
pc/src/store/action/A2Main.ts

@@ -10,9 +10,14 @@ export const A2_APIgetGoodsList = (data: A2getGoodsDataType) => {
     const res = await http.post("show/goods/pageList", data);
     const res = await http.post("show/goods/pageList", data);
 
 
     if (res.code === 0) {
     if (res.code === 0) {
+      const obj = {
+        list: res.data.records,
+        total: res.data.total,
+      };
+
       dispatch({
       dispatch({
         type: "main/goodsList",
         type: "main/goodsList",
-        payload: res.data.records,
+        payload: obj,
       });
       });
     }
     }
   };
   };
@@ -30,7 +35,7 @@ export const A2_APIgetSelectData = (type: "age" | "texture") => {
       const data = res.data.map((v: any) => ({ value: v.name, label: v.name }));
       const data = res.data.map((v: any) => ({ value: v.name, label: v.name }));
       data.unshift({
       data.unshift({
         value: "",
         value: "",
-        label: type === "age" ? "全部年代" : "全部种类",
+        label: type === "age" ? "全部年代" : "全部",
       });
       });
 
 
       if (type === "age") {
       if (type === "age") {

+ 5 - 2
pc/src/store/reducer/A2Main.ts

@@ -9,7 +9,10 @@ const initState = {
     txt: "",
     txt: "",
   },
   },
   // 文物列表数据
   // 文物列表数据
-  goodsList: [] as A2GoodsType[],
+  goodsList: {
+    list: [] as A2GoodsType[],
+    total: 0,
+  },
   // 下拉框数据
   // 下拉框数据
   selectData: {
   selectData: {
     texture: [],
     texture: [],
@@ -20,7 +23,7 @@ const initState = {
 // 定义 action 类型
 // 定义 action 类型
 type Props =
 type Props =
   | { type: "main/lookVideo"; payload: A2VideoType }
   | { type: "main/lookVideo"; payload: A2VideoType }
-  | { type: "main/goodsList"; payload: A2GoodsType[] }
+  | { type: "main/goodsList"; payload: { list: A2GoodsType[]; total: number } }
   | { type: "main/goodsSelect"; payload: A2SelectType };
   | { type: "main/goodsSelect"; payload: A2SelectType };
 // 频道 reducer
 // 频道 reducer
 export default function loginReducer(state = initState, action: Props) {
 export default function loginReducer(state = initState, action: Props) {

+ 3 - 2
pc/src/types/store/A2Main.d.ts

@@ -33,8 +33,9 @@ export type A2getGoodsDataType = {
   dictAge: string;
   dictAge: string;
   dictTexture: string;
   dictTexture: string;
   searchKey: string;
   searchKey: string;
-  pageNum: 1;
-  pageSize: 9999;
+  pageNum: number;
+  pageSize: number;
+  type:string
 };
 };
 
 
 export type A2SelectItemType = {
 export type A2SelectItemType = {

+ 1 - 1
pc/src/utils/env.ts

@@ -14,4 +14,4 @@ export type envDataType = {
 export const envData = staticData as envDataType[];
 export const envData = staticData as envDataType[];
 
 
 //@ts-ignore
 //@ts-ignore
-export const envUrl = `${staticUrl}/staticData`
+export const envUrl =staticUrl