shaogen1995 преди 1 година
родител
ревизия
0ac1dde010
променени са 30 файла, в които са добавени 998 реда и са изтрити 64 реда
  1. BIN
      pc/public/staticData/goods/icon1.png
  2. BIN
      pc/public/staticData/goods/icon1Ac.png
  3. BIN
      pc/public/staticData/goods/icon2.png
  4. BIN
      pc/public/staticData/goods/icon3.png
  5. BIN
      pc/public/staticData/goods/icon4.png
  6. BIN
      pc/public/staticData/goods/icon5.png
  7. BIN
      pc/public/staticData/goods/icon5Ac.png
  8. BIN
      pc/public/staticData/goods/icon6.png
  9. BIN
      pc/public/staticData/goods/icon6Ac.png
  10. BIN
      pc/public/staticData/goods/icon7.png
  11. BIN
      pc/public/staticData/goods/icon7Ac.png
  12. 0 0
      pc/public/staticData/home/close.png
  13. 0 0
      pc/public/staticData/home/homeBg.jpg
  14. 0 0
      pc/public/staticData/home/homeBtn.png
  15. 0 0
      pc/public/staticData/home/logo.png
  16. 0 1
      pc/src/pages/A1Home/index.module.scss
  17. 6 3
      pc/src/pages/A1Home/index.tsx
  18. 0 1
      pc/src/pages/A2Main/Tab4/index.module.scss
  19. 2 2
      pc/src/pages/A2Main/Tab4/index.tsx
  20. 79 8
      pc/src/pages/A2Main/Tab4Info/index.module.scss
  21. 188 44
      pc/src/pages/A2Main/Tab4Info/index.tsx
  22. 230 0
      pc/src/pages/A2Main/Tab4Msg/index.module.scss
  23. 178 0
      pc/src/pages/A2Main/Tab4Msg/index.tsx
  24. 153 0
      pc/src/pages/A2Main/Tab4S3/index.module.scss
  25. 136 0
      pc/src/pages/A2Main/Tab4S3/index.tsx
  26. 5 0
      pc/src/pages/A2Main/Tab4S4/index.module.scss
  27. 14 0
      pc/src/pages/A2Main/Tab4S4/index.tsx
  28. 2 3
      pc/src/pages/A2Main/index.tsx
  29. 0 1
      pc/src/pages/A3Goods/index.module.scss
  30. 5 1
      pc/src/pages/A3Goods/index.tsx

BIN
pc/public/staticData/goods/icon1.png


BIN
pc/public/staticData/goods/icon1Ac.png


BIN
pc/public/staticData/goods/icon2.png


BIN
pc/public/staticData/goods/icon3.png


BIN
pc/public/staticData/goods/icon4.png


BIN
pc/public/staticData/goods/icon5.png


BIN
pc/public/staticData/goods/icon5Ac.png


BIN
pc/public/staticData/goods/icon6.png


BIN
pc/public/staticData/goods/icon6Ac.png


BIN
pc/public/staticData/goods/icon7.png


BIN
pc/public/staticData/goods/icon7Ac.png


pc/src/assets/img/close.png → pc/public/staticData/home/close.png


pc/src/assets/img/homeBg.jpg → pc/public/staticData/home/homeBg.jpg


pc/src/assets/img/homeBtn.png → pc/public/staticData/home/homeBtn.png


pc/src/assets/img/logo.png → pc/public/staticData/home/logo.png


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

@@ -1,5 +1,4 @@
 .A1Home{
-  background-image: url('../../assets/img/homeBg.jpg');
   background-size: 100% 100%;
   position: relative;
   :global{

+ 6 - 3
pc/src/pages/A1Home/index.tsx

@@ -1,12 +1,15 @@
 import React from "react";
 import styles from "./index.module.scss";
-import btnImg from "@/assets/img/homeBtn.png";
 import history from "@/utils/history";
+import { envUrl } from "@/utils/env";
 function A1Home() {
   return (
-    <div className={styles.A1Home}>
+    <div
+      className={styles.A1Home}
+      style={{ backgroundImage: `url(${envUrl}/home/homeBg.jpg)` }}
+    >
       <div className="btn" onClick={() => history.push("/main")}>
-        <img src={btnImg} alt="" />
+        <img src={`${envUrl}/home/homeBtn.png`} alt="" />
       </div>
     </div>
   );

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

@@ -158,7 +158,6 @@
       flex-wrap: wrap;
 
       .tab4Mrow {
-        transition: all .2s;
         cursor: pointer;
         width: 23.5%;
         height: 46%;

+ 2 - 2
pc/src/pages/A2Main/Tab4/index.tsx

@@ -21,7 +21,7 @@ import "swiper/css/free-mode";
 import Tab4Info from "../Tab4Info";
 
 const typeArr = [
-  { id: "", name: "二维文物" },
+  { id: "img", name: "二维文物" },
   { id: "model", name: "三维文物" },
 ];
 
@@ -38,7 +38,7 @@ function Tab4() {
     searchKey: "",
     pageNum: 1,
     pageSize: 8,
-    type: "",
+    type: "img",
   });
 
   // 发送请求函数

+ 79 - 8
pc/src/pages/A2Main/Tab4Info/index.module.scss

@@ -74,7 +74,7 @@
     // 其他附件
     .t4IFileBox {
       width: 1252px;
-      height: calc(100% - 230px);
+      height: calc(100% - 240px);
       position: absolute;
       left: 50%;
       top: 140px;
@@ -95,6 +95,13 @@
           max-width: 100%;
           max-height: 100%;
         }
+        img{
+          object-fit: contain !important;
+        }
+        .lookImg{
+          background-color:transparent;
+          // opacity: 0 !important;
+        }
       }
 
       .R1_rowAc {
@@ -121,8 +128,8 @@
       cursor: pointer;
       position: absolute;
       top: 50%;
-      width: 50px;
-      height: 50px;
+      width: 40px;
+      height: 40px;
       left: 30px;
       z-index: 12;
       transform: translateY(-50%);
@@ -135,8 +142,8 @@
       cursor: pointer;
       position: absolute;
       top: 50%;
-      width: 50px;
-      height: 50px;
+      width: 40px;
+      height: 40px;
       right: 30px;
       z-index: 12;
       transform: translateY(-50%);
@@ -153,13 +160,77 @@
     // 底部文字集合
     .t4ITxts {
       position: absolute;
-      padding: 0 10px;
+      padding: 0 40px;
       text-align: center;
       z-index: 10;
       bottom: 5px;
-      left: 0;
-      width: 100%;
+      left: 50%;
+      transform: translateX(-50%);
+      width: 80%;
       height: 80px;
+      font-size: 16px;
+      color: #fff;
+      overflow-y: auto;
+
+      span {
+        font-weight: 700;
+      }
+    }
+
+    .rightIconBox {
+      position: absolute;
+      z-index: 10;
+      bottom: 20px;
+      right: 30px;
+      width: 40px;
+
+      .rightIconRow {
+        position: relative;
+        cursor: pointer;
+        margin-bottom: 15px;
+        // 点赞
+
+        .moveImg {
+          pointer-events: none;
+          position: absolute;
+          bottom: -10px;
+          left: -20px;
+          color: var(--themeColor);
+          width: 60px;
+
+          &>img {
+            width: 40px;
+            height: 40px;
+
+          }
+        }
+      }
+    }
+
+    // 滚动弹幕
+    .barrMove {
+      z-index: 11;
+      pointer-events: none;
+      position: absolute;
+      right: -1300px;
+      top: 130px;
+      background-color: rgba(98, 82, 65, 0.6);
+      backdrop-filter: blur(6px);
+      padding: 8px 30px;
+      border-radius: 36px;
+      overflow: hidden;
+
+      &>h3 {
+        font-size: 18px;
+        color: #fff;
+      }
+
+      &>P {
+        font-size: 12px;
+        color: #fff;
+        opacity: .6;
+      }
+
     }
 
   }

+ 188 - 44
pc/src/pages/A2Main/Tab4Info/index.tsx

@@ -30,6 +30,9 @@ 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";
+import { gsap } from "gsap";
+import Tab4Msg from "../Tab4Msg";
+import Tab4S3 from "../Tab4S3";
 
 type Props = {
   isOpen: boolean;
@@ -52,9 +55,10 @@ function Tab4Info({ isOpen, id, closePage }: Props) {
 
   // 音频
   const [right1, setRight1] = useState({ show: false, url: "" });
+  const audioUrlRef = useRef("");
 
-  // 留言板(默认显示),传递 doneIn 到二级页面 看看是否开启了  留言到后端的  功能
-  const [right2, setRight2] = useState({ done: true, doneIn: false });
+  // 留言板(默认显示),传递 到二级页面 看看是否开启了  留言到后端的  功能
+  const [right2, setRight2] = useState(false);
 
   //问答
   const [right3, setRight3] = useState(false);
@@ -102,7 +106,7 @@ function Tab4Info({ isOpen, id, closePage }: Props) {
   }, [id, right7]);
 
   // 留言-知识-问答 弹窗的选中状态(打开)
-  const [leftAc, setLeftAc] = useState(1);
+  const [rightPageAc, setRightPageAc] = useState<0 | 2 | 3 | 4>(0);
 
   // 问答数组
   const [question, setQuestion] = useState<A2QuestionType[]>([]);
@@ -180,8 +184,8 @@ function Tab4Info({ isOpen, id, closePage }: Props) {
               setRight5({ show: true, done: true });
             }
 
-            // 文物的弹幕留言开关 和总 弹幕开关都开启了
-            if (info.isBarrage) setRight2({ done: true, doneIn: true });
+            // 文物的弹幕留言开关 和总 弹幕开关都开启了(可以在二级页面发送接口留言)
+            if (info.isBarrage) setRight2(true);
           }
         }
 
@@ -204,7 +208,8 @@ function Tab4Info({ isOpen, id, closePage }: Props) {
         // 有上传音频
         const isAudioObj = file.find((v) => v.type === "audio");
         if (isAudioObj) {
-          setRight1({ show: isOpen ? true : false, url: isAudioObj.filePath });
+          setRight1({ show: !isOpen, url: isAudioObj.filePath });
+          audioUrlRef.current = isAudioObj.filePath;
         }
 
         setInfo(info);
@@ -229,6 +234,35 @@ function Tab4Info({ isOpen, id, closePage }: Props) {
     [isOpen]
   );
 
+  // 有关音频
+  useEffect(() => {
+    if (right1.url) {
+      // 如果是从 文物  详情 进来---直接播放音频
+      window.setTimeout(() => {
+        const dom: HTMLAudioElement | null = document.querySelector("#myAudio");
+
+        if (dom) {
+          dom.onended = () => {
+            // console.log("-------音频播放结束");
+            setRight1({ show: false, url: audioUrlRef.current });
+          };
+          // 音频的状态
+          if (!isOpen) dom.play();
+        }
+      }, 100);
+    }
+  }, [isOpen, right1.url]);
+
+  // 打开和关闭音频
+  const audioCutFu = useCallback((val: boolean) => {
+    const dom: HTMLAudioElement | null = document.querySelector("#myAudio");
+    if (dom) {
+      if (!val) dom.play();
+      else dom.pause();
+      setRight1({ show: !val, url: audioUrlRef.current });
+    }
+  }, []);
+
   useEffect(() => {
     getDataFu(id);
     return () => {
@@ -256,6 +290,13 @@ function Tab4Info({ isOpen, id, closePage }: Props) {
     return arr;
   }, [fileList]);
 
+  // 当前默认展示什么模块(优先级按照 模型-视频-图片)
+  useEffect(() => {
+    if (fileList.model.length) setType("model");
+    else if (fileList.video.length) setType("video");
+    else setType("img");
+  }, [fileList]);
+
   // 在页面展示的数组
   const list = useMemo(() => {
     return fileList[type];
@@ -263,7 +304,6 @@ function Tab4Info({ isOpen, id, closePage }: Props) {
 
   // 当前显示的 索引
   const [showInd, setShowInd] = useState(0);
-
   const cutIndFu = useCallback(
     (num: number) => {
       setShowInd(showInd + num);
@@ -271,47 +311,16 @@ function Tab4Info({ isOpen, id, closePage }: Props) {
     [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)` }}
     >
+      {/* 音频控件 */}
+      {right1.url ? (
+        <audio hidden src={baseURL + right1.url} controls id="myAudio"></audio>
+      ) : null}
+
       {/* 返回按钮 */}
       <div className="t4ItoBack" onClick={closePage}>
         <img src={toBackImg} alt="" />
@@ -389,7 +398,142 @@ function Tab4Info({ isOpen, id, closePage }: Props) {
       </div>
 
       {/* 底部文字介绍集合 */}
-      <div className="t4ITxts">{tstS}</div>
+      <div className="t4ITxts myscroll">
+        {info.dictTexture ? (
+          <>
+            <span>类别:</span>
+            {info.dictTexture}&emsp;
+          </>
+        ) : null}
+
+        {info.dictAge ? (
+          <>
+            <span>年代:</span>
+            {info.dictAge}&emsp;
+          </>
+        ) : null}
+        {info.dictLevel ? (
+          <>
+            <span>级别:</span>
+            {info.dictLevel}&emsp;
+          </>
+        ) : null}
+        {info.description ? (
+          <>
+            <span>简介:</span>
+            {info.description}&emsp;
+          </>
+        ) : null}
+      </div>
+
+      {/* 右侧所有按钮图标 */}
+      <div className="rightIconBox">
+        {/* 音频 */}
+        {right1.url ? (
+          <div
+            className="rightIconRow"
+            onClick={() => audioCutFu(right1.show)}
+            title={right1.show ? "关闭音频" : "打开音频"}
+          >
+            <img
+              src={`${envUrl}/goods/icon1${right1.show ? "Ac" : ""}.png`}
+              alt=""
+            />
+          </div>
+        ) : null}
+
+        {/* 留言板 */}
+        <div
+          hidden={barrage.length<=0}
+          className="rightIconRow"
+          onClick={() => setRightPageAc(2)}
+          title="留言板"
+        >
+          <img src={`${envUrl}/goods/icon2.png`} alt="" />
+        </div>
+
+        {/* 问答 */}
+        {right3 ? (
+          <div
+            className="rightIconRow"
+            onClick={() => setRightPageAc(3)}
+            title="问答"
+          >
+            <img src={`${envUrl}/goods/icon3.png`} alt="" />
+          </div>
+        ) : null}
+
+        {/* 知识 */}
+        {right4 ? (
+          <div
+            className="rightIconRow"
+            onClick={() => setRightPageAc(4)}
+            title="知识"
+          >
+            <img src={`${envUrl}/goods/icon4.png`} alt="" />
+          </div>
+        ) : null}
+
+        {/* 弹幕 */}
+        {right5.done ? (
+          <div
+            className="rightIconRow"
+            title={right5.show ? "关闭弹幕" : "开启弹幕"}
+            onClick={() => setRight5({ show: !right5.show, done: true })}
+          >
+            <img
+              src={`${envUrl}/goods/icon5${right5.show ? "Ac" : ""}.png`}
+              alt=""
+            />
+          </div>
+        ) : null}
+
+        {/* 点赞 */}
+        <div
+          className="rightIconRow"
+          onClick={() => likeClickFu()}
+          title="点赞"
+        >
+          <img src={`${envUrl}/goods/icon6${right6 ? "Ac" : ""}.png`} alt="" />
+          <div className="moveImg" hidden={!right6}>
+            +1
+          </div>
+        </div>
+
+        {/* 分享 */}
+
+        <div
+          className="rightIconRow"
+          onClick={() => fenXClickFu()}
+          title="分享"
+        >
+          <img src={`${envUrl}/goods/icon7${right7 ? "Ac" : ""}.png`} alt="" />
+        </div>
+      </div>
+
+      {/* 弹幕的盒子 */}
+      {barrageAll.length ? (
+        <div className="barrMove" ref={barrMoveRef} hidden={!right5.show}>
+          <h3>{barrageAll[barrInd].name}</h3>
+          <p>
+            {barrageAll[barrInd].authorName}&nbsp;
+            {barrageAll[barrInd].createTime}
+            &nbsp;观&nbsp;[{barrageAll[barrInd].goodsName}]&nbsp;有感
+          </p>
+        </div>
+      ) : null}
+
+      {/* 留言板 - 知识 - 问答 */}
+      {rightPageAc === 2 ? (
+        <Tab4Msg
+          btnOkFlag={right2}
+          barrageList={barrage}
+          goodsId={id}
+          closeFu={() => setRightPageAc(0)}
+        />
+      ) : rightPageAc === 3 ? (
+        <Tab4S3 closeFu={() => setRightPageAc(0)} questionList={question}/>
+      ) : null}
     </div>
   );
 }

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

@@ -0,0 +1,230 @@
+.Tab4Msg {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 99;
+  background-color: rgba(0, 0, 0, .8);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+
+  :global {
+    .tab4Mmain {
+      background-color: #7B6F4E;
+      border-top: 3px solid var(--themeColor);
+      width: 1050px;
+      position: relative;
+      padding: 10px 40px 30px;
+
+      .tab4Mclose {
+        position: absolute;
+        right: 15px;
+        top: 10px;
+        color: var(--themeColor);
+        font-size: 24px;
+        cursor: pointer;
+      }
+
+      .tab4MTop {
+        font-weight: 700;
+        font-size: 24px;
+        letter-spacing: 4px;
+        color: var(--themeColor);
+        border-bottom: 1px solid var(--themeColor);
+        padding-bottom: 10px;
+        position: relative;
+
+        &::before {
+          content: '';
+          position: absolute;
+          bottom: -1px;
+          left: 0;
+          width: 80px;
+          height: 3px;
+          background-color: var(--themeColor);
+        }
+      }
+
+      .tab4MlistNone {
+        margin-top: 20px;
+        width: 100%;
+        min-height: 200px;
+        max-height: 400px;
+        color: #fff;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        font-size: 24px;
+        letter-spacing: 4px;
+        color: #fff;
+
+      }
+
+      .tab4Mlist {
+        margin-top: 20px;
+        width: 100%;
+        min-height: 200px;
+        max-height: 400px;
+        overflow-y: auto;
+        padding: 0px 20px 20px 0;
+        color: #fff;
+        position: relative;
+
+
+        .tab4MlistRow {
+          .tab4Mlist_Title {
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            margin-bottom: 8px;
+
+            .tab4Mlist_Title_l {
+              font-size: 18px;
+            }
+
+            .tab4Mlist_Title_r {
+              font-size: 14px;
+              opacity: .6;
+            }
+          }
+
+          .tab4Mlist_Txt {
+            font-size: 14px;
+            line-height: 18px;
+            word-wrap: break-word;
+            margin-bottom: 24px;
+          }
+        }
+      }
+
+      .tab4MF_main {
+        border-top: 1px solid var(--themeColor);
+        padding-top: 15px;
+        width: 100%;
+        position: relative;
+
+        &::before {
+          content: '';
+          position: absolute;
+          top: -4px;
+          right: 0;
+          width: 80px;
+          height: 3px;
+          background-color: var(--themeColor);
+        }
+
+        .tab4MF_code {
+          position: absolute;
+          top: 136px;
+          right: 194px;
+          z-index: 10;
+        }
+
+        .tab4MF_btn {
+          text-align: center;
+        }
+
+        .F_codeImg {
+          position: absolute;
+          z-index: 99;
+          right: 85px;
+          top: 131px;
+
+          width: 100px;
+
+          &>img {
+            cursor: pointer;
+          }
+
+        }
+
+        // antd表单样式重置
+        .ant-form-item-label>label {
+          color: #fff;
+        }
+
+        .ant-input-affix-wrapper {
+          background-color: rgba(133, 127, 108, .5);
+          // border-color: rgba(255, 255, 255, .6);
+
+          .ant-input {
+            color: #fff;
+            background-color: transparent;
+
+            /*修改提示文字的颜色*/
+            &::-webkit-input-placeholder {
+              /* WebKit browsers */
+              color: rgba(255, 255, 255, .6);
+            }
+
+            &:-moz-placeholder {
+              /* Mozilla Firefox 4 to 18 */
+              color: rgba(255, 255, 255, .6);
+            }
+
+            &::-moz-placeholder {
+              /* Mozilla Firefox 19+ */
+              color: rgba(255, 255, 255, .6);
+            }
+
+            &:-ms-input-placeholder {
+              /* Internet Explorer 10+ */
+              color: rgba(255, 255, 255, .6);
+            }
+
+          }
+
+          .ant-input-show-count-suffix {
+            color: rgba(255, 255, 255, .6);
+          }
+
+          .ant-input-data-count {
+            right: 4px;
+            color: rgba(255, 255, 255, .6);
+          }
+
+        }
+
+        .ant-form-item-explain-error {
+          color: #fff;
+        }
+
+        .ant-btn-primary {
+          background-color: #F0D99C !important;
+          color: #625241 !important;
+          font-size: 18px;
+          border: none !important;
+          width: 126px;
+          height: 36px;
+          line-height: 26px;
+          text-align: center;
+        }
+
+        .ant-btn-default {
+          background-color: transparent !important;
+          color: #fff !important;
+          font-size: 18px;
+          border-color: #F0D99C !important;
+          width: 126px;
+          height: 36px;
+          line-height: 26px;
+          text-align: center;
+        }
+
+        .F_tit {
+          text-align: center;
+          color: #fff;
+        }
+
+      }
+
+      .noMsgBtn {
+        margin-top: 20px;
+        text-align: center;
+      }
+
+    }
+  }
+}

+ 178 - 0
pc/src/pages/A2Main/Tab4Msg/index.tsx

@@ -0,0 +1,178 @@
+import React, { useCallback, useEffect, useState } from "react";
+import styles from "./index.module.scss";
+import { CloseOutlined } from "@ant-design/icons";
+import { A2BarrageType, A2R_fSaveType } from "@/types";
+import { A2_APIgetRandCode, A2_APIsaveBarrage } from "@/store/action/A2Main";
+import { MessageFu } from "@/utils/message";
+import { Button, Form, Input } from "antd";
+import TextArea from "antd/es/input/TextArea";
+
+type Props = {
+  closeFu: () => void;
+  btnOkFlag: boolean; //是否开启的留言 能发送后端的开关
+  barrageList: A2BarrageType[]; //所有留言的数组
+  goodsId: number;
+};
+
+function Tab4Msg({ closeFu, btnOkFlag, barrageList, goodsId }: Props) {
+  const [codeImg, setCodeImg] = useState<any>("");
+
+  // 获取验证码函数
+  const getRandCodeFu = useCallback(async () => {
+    const res: any = await A2_APIgetRandCode();
+    const reader = new FileReader();
+    reader.readAsDataURL(res);
+    reader.onload = () => {
+      setCodeImg(reader.result);
+    };
+    // console.log(123, res);
+  }, []);
+
+  useEffect(() => {
+    getRandCodeFu();
+  }, [getRandCodeFu]);
+
+  // 没有通过校验
+  const onFinishFailed = useCallback(() => {}, []);
+
+  // 通过校验
+  const onFinish = useCallback(
+    async (value: A2R_fSaveType) => {
+      const obj = {
+        ...value,
+        goodsId,
+      };
+      const res = await A2_APIsaveBarrage(obj);
+      if (res.code === 0) {
+        MessageFu.success("留言成功,等待审核");
+      }
+    },
+    [goodsId]
+  );
+
+  return (
+    <div className={styles.Tab4Msg}>
+      <div className="tab4Mmain">
+        {/* 关闭按钮 */}
+        <div className="tab4Mclose" onClick={closeFu}>
+          <CloseOutlined />
+        </div>
+        <div className="tab4MTop">留言板</div>
+
+        {/* 留言列表 */}
+
+        {barrageList.length > 0 ? (
+          <div className="tab4Mlist myscroll">
+            {barrageList.map((v) => (
+              <div className="tab4MlistRow" key={v.id}>
+                <div className="tab4Mlist_Title">
+                  <div className="tab4Mlist_Title_l">{v.authorName}</div>
+                  <div className="tab4Mlist_Title_r">{v.createTime}</div>
+                </div>
+                <div className="tab4Mlist_Txt">{v.name}</div>
+              </div>
+            ))}
+          </div>
+        ) : (
+          <div className="tab4MlistNone">暂无留言</div>
+        )}
+
+        {/* 表单主体 */}
+        {btnOkFlag ? (
+          <div className="tab4MF_main">
+            <Form
+              labelCol={{ span: 0 }}
+              name="basic"
+              onFinish={onFinish}
+              onFinishFailed={onFinishFailed}
+              autoComplete="off"
+            >
+              <Form.Item
+                label="留言内容"
+                name="name"
+                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();
+                    },
+                  },
+                ]}
+              >
+                <TextArea
+                  rows={4}
+                  placeholder="请输入内容"
+                  showCount
+                  maxLength={50}
+                />
+              </Form.Item>
+
+              <Form.Item
+                label="您的昵称"
+                name="authorName"
+                rules={[{ required: true, message: "内容不能为空" }]}
+                getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+              >
+                <Input
+                  style={{ width: 300 }}
+                  maxLength={8}
+                  showCount
+                  placeholder="请输入内容"
+                />
+              </Form.Item>
+
+              <Form.Item
+                className="tab4MF_code"
+                label="验证码"
+                name="randCode"
+                rules={[{ required: true, message: "内容不能为空" }]}
+                getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+              >
+                <Input
+                  style={{ width: 200 }}
+                  maxLength={5}
+                  showCount
+                  placeholder="请输入内容"
+                />
+              </Form.Item>
+
+              {/* 验证码图 */}
+              <div className="F_codeImg">
+                <img src={codeImg} alt="" onClick={() => getRandCodeFu()} />
+              </div>
+
+              {/* 确定和取消按钮 */}
+              <br />
+              <Form.Item className="tab4MF_btn">
+                <Button type="primary" htmlType="submit">
+                  留言
+                </Button>
+                &emsp;
+                <Button onClick={() => closeFu()}>取消</Button>
+              </Form.Item>
+            </Form>
+            {/* 最后提示语句 */}
+            <div className="F_tit">
+              您的留言经审核并采纳后,才会在平台中公开展示
+            </div>
+          </div>
+        ) : (
+          <div className="noMsgBtn">
+            <Button onClick={() => closeFu()}>关闭</Button>
+          </div>
+        )}
+      </div>
+    </div>
+  );
+}
+
+const MemoTab4Msg = React.memo(Tab4Msg);
+
+export default MemoTab4Msg;

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

@@ -0,0 +1,153 @@
+.Tab4S3 {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 99;
+  background-color: rgba(0, 0, 0, .8);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+
+  :global {
+    .tab4S3main {
+      background-color: #7B6F4E;
+      border-top: 3px solid var(--themeColor);
+      width: 1050px;
+      position: relative;
+      padding: 10px 40px 30px;
+
+      .tab4S3close {
+        position: absolute;
+        right: 15px;
+        top: 10px;
+        color: var(--themeColor);
+        font-size: 24px;
+        cursor: pointer;
+      }
+
+      .tab4S3Top {
+        font-weight: 700;
+        font-size: 24px;
+        letter-spacing: 4px;
+        color: var(--themeColor);
+        border-bottom: 1px solid var(--themeColor);
+        padding-bottom: 10px;
+        position: relative;
+
+        &::before {
+          content: '';
+          position: absolute;
+          bottom: -1px;
+          left: 0;
+          width: 80px;
+          height: 3px;
+          background-color: var(--themeColor);
+        }
+      }
+
+      .tab4S3cenNone {
+        min-height: 200px;
+        color: #fff;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        font-size: 24px;
+        letter-spacing: 4px;
+        color: #fff;
+      }
+
+      .tab4S3cen {
+        min-height: 200px;
+        padding-top: 15px;
+        color: #fff;
+
+        .tab4S3cenTit {
+          margin-bottom: 15px;
+          font-size: 20px;
+        }
+
+        .left3Main {
+          width: 100%;
+          height: calc(100% - 40px);
+          max-height: 400px;
+          padding-right: 30px;
+          overflow-y: auto;
+
+          .left3MainRow {
+            font-size: 16px;
+            margin-bottom: 20px;
+
+            .left3MainRowT {
+              margin-bottom: 10px;
+              word-wrap: break-word;
+            }
+
+            .left3MainRowC {
+              padding-left: 15px;
+              cursor: pointer;
+              margin-bottom: 15px;
+              font-size: 14px;
+              word-wrap: break-word;
+
+              &:hover {
+                text-decoration: underline;
+                color: var(--themeColor);
+              }
+            }
+
+
+
+            .left3MainRowCX {
+              color: #FF5757;
+            }
+
+            .left3MainRowCD {
+              color: #8CFD79;
+            }
+
+            .left3MainRowCN {
+              pointer-events: none;
+            }
+
+
+            .left3Sta {
+              font-size: 14px;
+              margin-bottom: 5px;
+
+              .left3Sta1 {
+                color: #8CFD79;
+              }
+
+              .left3Sta2 {
+                color: #FF5757;
+              }
+            }
+
+            .left3Txt {
+              font-size: 14px;
+              word-wrap: break-word;
+            }
+          }
+        }
+      }
+
+      .tab4S3xBtn {
+        margin-top: 20px;
+        text-align: center;
+
+        .ant-btn-default {
+          background-color: transparent !important;
+          color: #fff !important;
+          font-size: 18px;
+          border-color: #F0D99C !important;
+          width: 126px;
+          height: 36px;
+          line-height: 26px;
+          text-align: center;
+        }
+      }
+    }
+  }
+}

+ 136 - 0
pc/src/pages/A2Main/Tab4S3/index.tsx

@@ -0,0 +1,136 @@
+import React, { useCallback, useEffect, useState } from "react";
+import styles from "./index.module.scss";
+import { CheckOutlined, CloseOutlined } from "@ant-design/icons";
+import { A2QuestionResType, A2QuestionType } from "@/types";
+import { A2_APIgoodsSaveAnswer } from "@/store/action/A2Main";
+import classNames from "classnames";
+import { Button } from "antd";
+
+const objC = {
+  0: "A",
+  1: "B",
+  2: "C",
+  3: "D",
+  4: "E",
+};
+
+type Props = {
+  closeFu: () => void;
+  questionList: A2QuestionType[];
+};
+
+function Tab4S3({ closeFu, questionList }: Props) {
+  const [listRes, setListRes] = useState<A2QuestionResType[]>([]);
+
+  useEffect(() => {
+    const arr = [] as A2QuestionResType[];
+    questionList.forEach((v) => {
+      const temp = JSON.parse(v.answer);
+      arr.push({
+        id: v.id,
+        txt: v.description,
+        goodsId: v.goodsId,
+        title: v.question,
+        ok: temp.correct,
+        answer: temp.answer,
+        done: false,
+        mySelect: "",
+      });
+    });
+    setListRes(arr);
+  }, [questionList]);
+
+  // 选择答案
+  const selecttFu = useCallback(
+    async (item: A2QuestionResType, val: string) => {
+      if (!item.done) {
+        const arr = listRes.map((v) => {
+          return {
+            ...v,
+            done: v.id === item.id ? true : v.done,
+            mySelect: v.id === item.id ? val : v.mySelect,
+          };
+        });
+        setListRes(arr);
+        // 发送请求
+        await A2_APIgoodsSaveAnswer(item.id, val === item.ok ? 1 : 0);
+      }
+    },
+    [listRes]
+  );
+
+  return (
+    <div className={styles.Tab4S3}>
+      <div className="tab4S3main">
+        {/* 关闭按钮 */}
+        <div className="tab4S3close" onClick={closeFu}>
+          <CloseOutlined />
+        </div>
+        <div className="tab4S3Top">问答</div>
+
+        {/* 主要内容 */}
+        {questionList.length ? (
+          <div className="tab4S3cen">
+            <div className="tab4S3cenTit">单选题</div>
+            <div className="left3Main myscroll">
+              {listRes.map((v1, i1) => (
+                <div className="left3MainRow" key={v1.id}>
+                  <div className="left3MainRowT">
+                    {i1 + 1}、{v1.title}
+                  </div>
+                  {v1.answer.map((v2, i2) => (
+                    <div
+                      key={v2.val}
+                      className={classNames(
+                        "left3MainRowC",
+                        v1.done ? "left3MainRowCN" : "",
+                        v1.ok === v2.val && v1.done ? "left3MainRowCD" : "",
+                        v1.mySelect === v2.val && v1.done
+                          ? "left3MainRowCX"
+                          : ""
+                      )}
+                      onClick={() => selecttFu(v1, v2.val)}
+                    >
+                      {Reflect.get(objC, i2)}:{v2.name}
+                    </div>
+                  ))}
+                  {/* 回答情况 */}
+                  <div className="left3Sta" hidden={!v1.done}>
+                    {v1.ok === v1.mySelect ? (
+                      <div className="left3Sta1">
+                        恭喜你,回答正确&emsp;
+                        <CheckOutlined />
+                      </div>
+                    ) : (
+                      <div className="left3Sta2">
+                        很遗憾,回答错误&emsp;
+                        <CloseOutlined />
+                      </div>
+                    )}
+                  </div>
+                  {/* 说明 */}
+                  <div className="left3Txt" hidden={!v1.done || !v1.txt}>
+                    {/* 正确答案:{v1.ok}
+              <br /> */}
+                    题目解析:{v1.txt}
+                  </div>
+                </div>
+              ))}
+            </div>
+          </div>
+        ) : (
+          <div className="tab4S3cenNone">暂无题目</div>
+        )}
+
+        {/* 退出按钮 */}
+        <div className="tab4S3xBtn" onClick={closeFu}>
+          <Button>关闭</Button>
+        </div>
+      </div>
+    </div>
+  );
+}
+
+const MemoTab4S3 = React.memo(Tab4S3);
+
+export default MemoTab4S3;

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

@@ -0,0 +1,5 @@
+.Tab4S4{
+  :global{
+    
+  }
+}

+ 14 - 0
pc/src/pages/A2Main/Tab4S4/index.tsx

@@ -0,0 +1,14 @@
+import React from "react";
+import styles from "./index.module.scss";
+ function Tab4S4() {
+  
+  return (
+    <div className={styles.Tab4S4}>
+      <h1>Tab4S4</h1>
+    </div>
+  )
+}
+
+const MemoTab4S4 = React.memo(Tab4S4);
+
+export default MemoTab4S4;

+ 2 - 3
pc/src/pages/A2Main/index.tsx

@@ -1,11 +1,10 @@
 /* eslint-disable jsx-a11y/iframe-has-title */
 import React, { useCallback, useState } from "react";
 import styles from "./index.module.scss";
-import LogoImg from "@/assets/img/logo.png";
 import classNames from "classnames";
 import history from "@/utils/history";
 import A0Map from "../A0Map";
-import { envData, envDataSonType, envDataType } from "@/utils/env";
+import { envData, envDataSonType, envDataType, envUrl } from "@/utils/env";
 import Tab1 from "./Tab1";
 import Tab4 from "./Tab4";
 
@@ -29,7 +28,7 @@ function A2Main() {
 
       {/* 左上方logo */}
       <div className="logo" title="首页" onClick={() => history.push("/")}>
-        <img src={LogoImg} alt="" />
+        <img src={`${envUrl}/home/logo.png`} alt="" />
       </div>
       {/* 底部轮播图 */}
       <div

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

@@ -5,7 +5,6 @@
   position: relative;
   backdrop-filter: blur(10px);
   padding-top: 30px;
-  background-image: url('../../assets/img/homeBg.jpg');
   background-size: 100% 100%;
   // :global {}
 }

+ 5 - 1
pc/src/pages/A3Goods/index.tsx

@@ -3,6 +3,7 @@ import styles from "./index.module.scss";
 import GoodsInfo from "../A2Main/GoodsInfo";
 import { urlParameter } from "@/utils/history";
 import { useLocation } from "react-router-dom";
+import { envUrl } from "@/utils/env";
 
 function A3Goods() {
   const [id, setId] = useState(0);
@@ -16,7 +17,10 @@ function A3Goods() {
   }, [location.search]);
 
   return (
-    <div className={styles.A3Goods}>
+    <div
+      className={styles.A3Goods}
+      style={{ backgroundImage: `url(${envUrl}/home/homeBg.jpg)` }}
+    >
       {id ? <GoodsInfo id={id} isOpen={true} /> : null}
     </div>
   );