shaogen1995 преди 2 години
родител
ревизия
34212fcfec
променени са 41 файла, в които са добавени 815 реда и са изтрити 17 реда
  1. BIN
      houtai/public/favicon.ico
  2. 30 0
      pc/package-lock.json
  3. 1 0
      pc/package.json
  4. BIN
      pc/public/favicon.ico
  5. BIN
      pc/public/swData/1/1.jpg
  6. BIN
      pc/public/swData/1/1.mp4
  7. 10 3
      pc/src/App.tsx
  8. BIN
      pc/src/assets/img/close.png
  9. BIN
      pc/src/assets/img/homeBg.jpg
  10. BIN
      pc/src/assets/img/homeBtn.png
  11. BIN
      pc/src/assets/img/logo.png
  12. BIN
      pc/src/assets/img/main/1.png
  13. BIN
      pc/src/assets/img/main/1Ac.png
  14. BIN
      pc/src/assets/img/main/2.png
  15. BIN
      pc/src/assets/img/main/2Ac.png
  16. BIN
      pc/src/assets/img/main/3.png
  17. BIN
      pc/src/assets/img/main/3Ac.png
  18. BIN
      pc/src/assets/img/main/4.png
  19. BIN
      pc/src/assets/img/main/4Ac.png
  20. BIN
      pc/src/assets/img/main/5.png
  21. BIN
      pc/src/assets/img/main/5Ac.png
  22. BIN
      pc/src/assets/img/main/icon_down.png
  23. BIN
      pc/src/assets/img/main/icon_up.png
  24. BIN
      pc/src/assets/img/pop.png
  25. BIN
      pc/src/assets/img/tempBg.jpg
  26. 49 4
      pc/src/assets/styles/base.css
  27. 60 4
      pc/src/assets/styles/base.less
  28. 26 0
      pc/src/components/NotFound/index.tsx
  29. 10 1
      pc/src/pages/A1Home/index.module.scss
  30. 7 4
      pc/src/pages/A1Home/index.tsx
  31. 111 0
      pc/src/pages/A2Main/SwiperCom/index.module.scss
  32. 82 0
      pc/src/pages/A2Main/SwiperCom/index.tsx
  33. 70 0
      pc/src/pages/A2Main/VideoBox/index.module.scss
  34. 52 0
      pc/src/pages/A2Main/VideoBox/index.tsx
  35. 138 0
      pc/src/pages/A2Main/index.module.scss
  36. 127 0
      pc/src/pages/A2Main/index.tsx
  37. 24 0
      pc/src/store/reducer/A2Main.ts
  38. 2 0
      pc/src/store/reducer/index.ts
  39. 1 0
      pc/src/types/index.d.ts
  40. 12 0
      pc/src/types/store/A2Main.d.ts
  41. 3 1
      pc/src/utils/history.ts

BIN
houtai/public/favicon.ico


+ 30 - 0
pc/package-lock.json

@@ -26,6 +26,7 @@
         "redux-devtools-extension": "^2.13.9",
         "redux-thunk": "^2.4.1",
         "sass": "^1.55.0",
+        "swiper": "^9.1.0",
         "typescript": "^4.8.4",
         "web-vitals": "^2.1.4"
       },
@@ -15100,6 +15101,11 @@
       "resolved": "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.0.3.tgz",
       "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
     },
+    "node_modules/ssr-window": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmmirror.com/ssr-window/-/ssr-window-4.0.2.tgz",
+      "integrity": "sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ=="
+    },
     "node_modules/stable": {
       "version": "0.1.8",
       "resolved": "https://registry.npmmirror.com/stable/-/stable-0.1.8.tgz",
@@ -15451,6 +15457,17 @@
         "boolbase": "~1.0.0"
       }
     },
+    "node_modules/swiper": {
+      "version": "9.2.3",
+      "resolved": "https://registry.npmmirror.com/swiper/-/swiper-9.2.3.tgz",
+      "integrity": "sha512-hxqcjIsYPP1fv+KIXPqGywl6ik8RBp0y0i9+TOIh55ca6SpZ5FrgNJ4QXPhsl6mlSBMEYPmh5zOKtZpI8zpWeQ==",
+      "dependencies": {
+        "ssr-window": "^4.0.2"
+      },
+      "engines": {
+        "node": ">= 4.7.0"
+      }
+    },
     "node_modules/symbol-tree": {
       "version": "3.2.4",
       "resolved": "https://registry.npmmirror.com/symbol-tree/-/symbol-tree-3.2.4.tgz",
@@ -28288,6 +28305,11 @@
       "resolved": "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.0.3.tgz",
       "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
     },
+    "ssr-window": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmmirror.com/ssr-window/-/ssr-window-4.0.2.tgz",
+      "integrity": "sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ=="
+    },
     "stable": {
       "version": "0.1.8",
       "resolved": "https://registry.npmmirror.com/stable/-/stable-0.1.8.tgz",
@@ -28576,6 +28598,14 @@
         }
       }
     },
+    "swiper": {
+      "version": "9.2.3",
+      "resolved": "https://registry.npmmirror.com/swiper/-/swiper-9.2.3.tgz",
+      "integrity": "sha512-hxqcjIsYPP1fv+KIXPqGywl6ik8RBp0y0i9+TOIh55ca6SpZ5FrgNJ4QXPhsl6mlSBMEYPmh5zOKtZpI8zpWeQ==",
+      "requires": {
+        "ssr-window": "^4.0.2"
+      }
+    },
     "symbol-tree": {
       "version": "3.2.4",
       "resolved": "https://registry.npmmirror.com/symbol-tree/-/symbol-tree-3.2.4.tgz",

+ 1 - 0
pc/package.json

@@ -21,6 +21,7 @@
     "redux-devtools-extension": "^2.13.9",
     "redux-thunk": "^2.4.1",
     "sass": "^1.55.0",
+    "swiper": "^9.1.0",
     "typescript": "^4.8.4",
     "web-vitals": "^2.1.4"
   },

BIN
pc/public/favicon.ico


BIN
pc/public/swData/1/1.jpg


BIN
pc/public/swData/1/1.mp4


+ 10 - 3
pc/src/App.tsx

@@ -9,22 +9,29 @@ import history from "./utils/history";
 
 // 使用 React.lazy 懒加载页面
 const A1Home = React.lazy(() => import("./pages/A1Home"));
+const A2Main = React.lazy(() => import("./pages/A2Main"));
+const NotFound = React.lazy(() => import("@/components/NotFound"));
 
 function App() {
   return (
-    <>
+    <div id="app">
       {/* 关于路由 */}
       <Router history={history}>
         <React.Suspense fallback={<SpinLoding />}>
           <Switch>
-            <Route path="/" component={A1Home} />
+            {/* 封面页 */}
+            <Route path="/" exact component={A1Home} />
+            {/* 地图页 */}
+            <Route path="/main" exact component={A2Main} />
+            {/* 找不到页面 */}
+            <Route path="*" component={NotFound} />
           </Switch>
         </React.Suspense>
       </Router>
 
       {/* 发送请求的加载组件 */}
       <AsyncSpinLoding />
-    </>
+    </div>
   );
 }
 

BIN
pc/src/assets/img/close.png


BIN
pc/src/assets/img/homeBg.jpg


BIN
pc/src/assets/img/homeBtn.png


BIN
pc/src/assets/img/logo.png


BIN
pc/src/assets/img/main/1.png


BIN
pc/src/assets/img/main/1Ac.png


BIN
pc/src/assets/img/main/2.png


BIN
pc/src/assets/img/main/2Ac.png


BIN
pc/src/assets/img/main/3.png


BIN
pc/src/assets/img/main/3Ac.png


BIN
pc/src/assets/img/main/4.png


BIN
pc/src/assets/img/main/4Ac.png


BIN
pc/src/assets/img/main/5.png


BIN
pc/src/assets/img/main/5Ac.png


BIN
pc/src/assets/img/main/icon_down.png


BIN
pc/src/assets/img/main/icon_up.png


BIN
pc/src/assets/img/pop.png


BIN
pc/src/assets/img/tempBg.jpg


+ 49 - 4
pc/src/assets/styles/base.css

@@ -31,7 +31,7 @@ ul {
   list-style: none;
 }
 body {
-  overflow-y: overlay;
+  overflow: hidden;
 }
 /* 文本域取消下拉 */
 textarea {
@@ -41,9 +41,54 @@ textarea {
 :root {
   --themeColor: #c8b992;
 }
-a {
-  color: var(--themeColor);
-}
 [hidden] {
   display: none !important;
 }
+/* 找不到页面 */
+.noFindPage {
+  opacity: 0;
+  transition: opacity 0.5s;
+}
+/* 兼容360浏览器的下拉框 */
+.ant-select-selector {
+  position: relative;
+  background-color: #ffffff;
+  border: 1px solid #d9d9d9;
+  transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
+}
+#root {
+  width: 100vw;
+  height: 100vh;
+  min-width: 1600px;
+  min-height: 900px;
+  overflow: hidden;
+}
+#root a {
+  color: var(--themeColor);
+}
+#root #app {
+  width: 100%;
+  height: 100%;
+}
+#root #app > div {
+  width: 100%;
+  height: 100%;
+}
+#root .myscroll::-webkit-scrollbar {
+  /*滚动条整体样式*/
+  width: 5px;
+  /*高宽分别对应横竖滚动条的尺寸*/
+  height: 1px;
+}
+#root .myscroll::-webkit-scrollbar-thumb {
+  /*滚动条里面小方块*/
+  border-radius: 10px;
+  -webkit-box-shadow: inset 0 0 5px transparent;
+  background: #8a7351;
+}
+#root .myscroll::-webkit-scrollbar-track {
+  /*滚动条里面轨道*/
+  -webkit-box-shadow: inset 0 0 5px transparent;
+  border-radius: 10px;
+  background: transparent;
+}

+ 60 - 4
pc/src/assets/styles/base.less

@@ -38,7 +38,7 @@ ul {
 }
 
 body {
-  overflow-y: overlay;
+  overflow: hidden;
 }
 
 /* 文本域取消下拉 */
@@ -51,10 +51,66 @@ textarea {
   --themeColor: #c8b992;
 }
 
-a {
-  color: var(--themeColor);
-}
+
 
 [hidden] {
   display: none !important;
+}
+
+/* 找不到页面 */
+.noFindPage {
+  opacity: 0;
+  transition: opacity .5s;
+}
+
+/* 兼容360浏览器的下拉框 */
+.ant-select-selector {
+  position: relative;
+  background-color: #ffffff;
+  border: 1px solid #d9d9d9;
+  transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
+}
+
+// 重置antd样式
+#root {
+  width: 100vw;
+  height: 100vh;
+  min-width: 1600px;
+  min-height: 900px;
+  overflow: hidden;
+
+  a {
+    color: var(--themeColor);
+  }
+
+  #app {
+    width: 100%;
+    height: 100%;
+
+    &>div {
+      width: 100%;
+      height: 100%;
+    }
+  }
+
+  .myscroll::-webkit-scrollbar {
+    /*滚动条整体样式*/
+    width: 5px;
+    /*高宽分别对应横竖滚动条的尺寸*/
+    height: 1px;
+  }
+
+  .myscroll::-webkit-scrollbar-thumb {
+    /*滚动条里面小方块*/
+    border-radius: 10px;
+    -webkit-box-shadow: inset 0 0 5px transparent;
+    background: #8a7351;
+  }
+
+  .myscroll::-webkit-scrollbar-track {
+    /*滚动条里面轨道*/
+    -webkit-box-shadow: inset 0 0 5px transparent;
+    border-radius: 10px;
+    background: transparent;
+  }
 }

+ 26 - 0
pc/src/components/NotFound/index.tsx

@@ -0,0 +1,26 @@
+import { Result } from "antd";
+import { useEffect, useRef } from "react";
+
+export default function NotFound() {
+  const timeRef = useRef(-1);
+
+  useEffect(() => {
+    timeRef.current = window.setTimeout(() => {
+      const dom: HTMLDivElement = document.querySelector(".noFindPage")!;
+      dom.style.opacity = "1";
+    }, 300);
+    return () => {
+      clearTimeout(timeRef.current);
+    };
+  }, []);
+
+  return (
+    <div className="noFindPage">
+      <Result
+        status="404"
+        title="404"
+        subTitle="页面找不到或没有权限,请联系管理员!"
+      />
+    </div>
+  );
+}

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

@@ -1,5 +1,14 @@
 .A1Home{
+  background-image: url('../../assets/img/homeBg.jpg');
+  background-size: 100% 100%;
+  position: relative;
   :global{
-    
+    .btn{
+      position: absolute;
+      left: 50%;
+      bottom: 100px;
+      cursor: pointer;
+      transform: translateX(-50%);
+    }
   }
 }

+ 7 - 4
pc/src/pages/A1Home/index.tsx

@@ -1,12 +1,15 @@
 import React from "react";
 import styles from "./index.module.scss";
- function A1Home() {
-  
+import btnImg from "@/assets/img/homeBtn.png";
+import history from "@/utils/history";
+function A1Home() {
   return (
     <div className={styles.A1Home}>
-      <h1>A1Home</h1>
+      <div className="btn" onClick={() => history.push("/main")}>
+        <img src={btnImg} alt="" />
+      </div>
     </div>
-  )
+  );
 }
 
 const MemoA1Home = React.memo(A1Home);

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

@@ -0,0 +1,111 @@
+.SwiperCom {
+  width: 100%;
+  height: 156px;
+  padding: 0 100px;
+
+  :global {
+    .SwiperComBox {
+      height: 100%;
+
+      .swiper-wrapper {
+        cursor: move;
+      }
+
+      .swiper-slide {
+        // width: 230px;
+        padding-right: 30px;
+        height: 156px;
+      }
+
+      .SwiperComRow {
+        cursor: pointer;
+        position: relative;
+        width: 100%;
+        height: 100%;
+        border-radius: 4px;
+        overflow: hidden;
+        color: #fff;
+        border: 2px solid transparent;
+
+        &>img {
+          width: 100%;
+          height: 100%;
+        }
+
+        &:hover {
+
+          border: 2px solid #F0D99C;
+
+        }
+
+
+        .SwiperComSm {
+          transition: all .2s;
+          position: absolute;
+          left: 0;
+          top: 0;
+          width: 100%;
+          height: 100%;
+          border-radius: 4px;
+          background-color: rgba(0, 0, 0, .5);
+
+          &>p {
+            padding: 10px;
+            text-align: center;
+            width: 100%;
+            letter-spacing: 2px;
+            color: #fff;
+            word-wrap: break-word;
+            position: absolute;
+            top: 50%;
+            left: 50%;
+            transform: translate(-50%, -50%);
+          }
+
+
+        }
+
+        .SwiperComName {
+          position: absolute;
+          bottom: 0;
+          left: 0;
+          width: 100%;
+          text-align: center;
+          opacity: 0;
+          transition: all .2s;
+          height: 40px;
+          line-height: 40px;
+          background-color: rgba(0, 0, 0, .5);
+          word-wrap: break-word;
+          padding: 0 8px;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+        }
+      }
+
+      .SwiperComRowAc {
+        border: 2px solid #F0D99C;
+
+        .SwiperComSm {
+          opacity: 0;
+        }
+
+        .SwiperComName {
+          opacity: 1;
+        }
+      }
+    }
+
+    .SwiperComBoxCen {
+      .swiper-wrapper {
+        display: flex;
+        justify-content: center;
+        cursor: default;
+      }
+    }
+
+
+
+  }
+}

+ 82 - 0
pc/src/pages/A2Main/SwiperCom/index.tsx

@@ -0,0 +1,82 @@
+import React, { useCallback, useEffect, useRef, useState } from "react";
+import styles from "./index.module.scss";
+import { Swiper, SwiperSlide } from "swiper/react";
+import classNames from "classnames";
+
+// Import Swiper styles
+import "swiper/css";
+import { envUrl } from "@/utils/history";
+import { A2SwType } from "@/types";
+import store from "@/store";
+
+type Props = {
+  data: A2SwType[];
+  type: number;
+};
+
+function SwiperCom({ data, type }: Props) {
+  useEffect(() => {
+    setActive(0);
+  }, [type]);
+
+  // 选中状态
+  const [active, setActive] = useState(0);
+  const cutAcFu = useCallback(
+    (item: A2SwType) => {
+      setActive(item.id);
+      if (type === 1) {
+        // 如果是历史,打开视频弹窗
+
+        store.dispatch({
+          type: "main/lookVideo",
+          payload: {
+            id: item.id,
+            title: item.info?.title!,
+            txt: item.info?.txt!,
+          },
+        });
+      }
+    },
+    [type]
+  );
+
+  // swiper实例
+  const mySwiperRef = useRef<any>(null);
+  return (
+    <div className={styles.SwiperCom}>
+      <Swiper
+        // centeredSlides={true}
+        spaceBetween={0}
+        slidesPerView={6}
+        className={classNames(
+          "SwiperComBox",
+          data.length <= 6 ? "SwiperComBoxCen" : ""
+        )}
+        onSwiper={(swiper) => (mySwiperRef.current = swiper)}
+      >
+        {data.map((v) => (
+          <SwiperSlide key={v.id}>
+            <div
+              title={v.name}
+              onClick={() => cutAcFu(v)}
+              className={classNames(
+                "SwiperComRow",
+                active === v.id ? "SwiperComRowAc" : ""
+              )}
+            >
+              <img src={envUrl + "/swData/1/1.jpg"} alt="" />
+              <div className="SwiperComSm">
+                <p>{v.name}</p>
+              </div>
+              <div className="SwiperComName">{v.name}</div>
+            </div>
+          </SwiperSlide>
+        ))}
+      </Swiper>
+    </div>
+  );
+}
+
+const MemoSwiperCom = React.memo(SwiperCom);
+
+export default MemoSwiperCom;

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

@@ -0,0 +1,70 @@
+.VideoBox {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 11;
+  width: 100%;
+  height: 100%;
+  backdrop-filter: blur(4px);
+  background-color: rgba(0, 0, 0, .5);
+  opacity: 0;
+  pointer-events: none;
+  transition: all .3s;
+  padding: 140px 100px 0 140px;
+
+  :global {
+    .videoClose {
+      position: absolute;
+      right: 40px;
+      top: 40px;
+      cursor: pointer;
+
+      // transform: scale(0.6);
+      &>img {
+        width: 46px;
+      }
+    }
+
+    .vidoMain {
+      width: 100%;
+      height: 100%;
+      display: flex;
+
+      .videobox {
+        width: 1000px;
+        max-height: 550px;
+
+        video {
+
+          width: 100%;
+          // height: 100%;
+        }
+      }
+
+      .videoTxt {
+        width: calc(100% - 1000px);
+        height: calc(100% - 160px);
+        overflow-y: auto;
+        padding: 0 30px;
+        color: #fff;
+
+        &>h3 {
+          font-size: 24px;
+          margin-bottom: 15px;
+        }
+
+        &>p {
+          font-size: 16px;
+          line-height: 24px;
+        }
+      }
+    }
+
+
+  }
+}
+
+.videoBoxAc {
+  opacity: 1;
+  pointer-events: auto;
+}

+ 52 - 0
pc/src/pages/A2Main/VideoBox/index.tsx

@@ -0,0 +1,52 @@
+import React from "react";
+import styles from "./index.module.scss";
+import classNames from "classnames";
+import { useSelector } from "react-redux";
+import store, { RootState } from "@/store";
+import { envUrl } from "@/utils/history";
+
+import closeImg from '@/assets/img/close.png'
+
+function VideoBox() {
+  const { videoInfo } = useSelector((state: RootState) => state.A2Main);
+
+  return (
+    <div
+      className={classNames(
+        styles.VideoBox,
+        videoInfo.id ? styles.videoBoxAc : ""
+      )}
+    >
+      <div
+        className="videoClose"
+        onClick={() =>
+          store.dispatch({
+            type: "main/lookVideo",
+            payload: {
+              id: 0,
+              title: "",
+              txt: "",
+            },
+          })
+        }
+      >
+        <img src={closeImg} alt="" />
+      </div>
+      {videoInfo.id ? (
+        <div className="vidoMain">
+          <div className="videobox">
+            <video src={envUrl + "/swData/1/1.mp4"} autoPlay controls></video>
+          </div>
+          <div className="videoTxt myscroll">
+            <h3>{videoInfo.title}</h3>
+            <p dangerouslySetInnerHTML={{ __html: videoInfo.txt }}></p>
+          </div>
+        </div>
+      ) : null}
+    </div>
+  );
+}
+
+const MemoVideoBox = React.memo(VideoBox);
+
+export default MemoVideoBox;

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

@@ -0,0 +1,138 @@
+.A2Main {
+  background-image: url('../../assets/img/tempBg.jpg');
+  background-size: 100% 100%;
+  position: relative;
+
+  :global {
+    .logo {
+      position: absolute;
+      z-index: 10;
+      top: 20px;
+      left: 20px;
+
+      &>img {
+        width: 180px;
+      }
+    }
+
+    .swBox {
+      transition: all .3s;
+      position: absolute;
+      z-index: 11;
+      width: 100%;
+      height: 100px;
+      left: 0;
+      bottom: 0;
+      backdrop-filter: blur(4px);
+
+      .swBoxMain {
+        width: 100%;
+        height: 100%;
+        border-radius: 50px 50px 0 0;
+
+        background-color: rgba(6, 10, 11, 0.80);
+
+      }
+
+      .top {
+        height: 100px;
+        display: flex;
+        position: relative;
+        align-items: center;
+        justify-content: center;
+        padding-right: 40px;
+
+        .row {
+          width: 70px;
+          height: 70px;
+          cursor: pointer;
+          background-size: 100% 100%;
+          transition: all .2s;
+          margin: 0 60px;
+        }
+
+        .row1 {
+          background-image: url('../../assets/img/main/1.png');
+
+          &:hover {
+            background-image: url('../../assets/img/main/1Ac.png');
+          }
+        }
+
+        .rowAc1 {
+          background-image: url('../../assets/img/main/1Ac.png');
+        }
+
+        .row2 {
+          background-image: url('../../assets/img/main/2.png');
+
+          &:hover {
+            background-image: url('../../assets/img/main/2Ac.png');
+          }
+        }
+
+        .rowAc2 {
+          background-image: url('../../assets/img/main/2Ac.png');
+        }
+
+        .row3 {
+          background-image: url('../../assets/img/main/3.png');
+
+          &:hover {
+            background-image: url('../../assets/img/main/3Ac.png');
+          }
+        }
+
+        .rowAc3 {
+          background-image: url('../../assets/img/main/3Ac.png');
+        }
+
+        .row4 {
+          background-image: url('../../assets/img/main/4.png');
+
+          &:hover {
+            background-image: url('../../assets/img/main/4Ac.png');
+          }
+        }
+
+        .rowAc4 {
+          background-image: url('../../assets/img/main/4Ac.png');
+        }
+
+        .row5 {
+          background-image: url('../../assets/img/main/5.png');
+
+          &:hover {
+            background-image: url('../../assets/img/main/5Ac.png');
+          }
+        }
+
+        .rowAc5 {
+          background-image: url('../../assets/img/main/5Ac.png');
+        }
+
+        .openIcon {
+          cursor: pointer;
+          transition: all .2s;
+          position: absolute;
+          top: 15px;
+          right: 38px;
+          width: 70px;
+          height: 70px;
+          background-image: url('../../assets/img/main/icon_down.png');
+          background-size: 100% 100%;
+        }
+
+      }
+    }
+
+    .swBox1 {
+      height: 270px;
+    }
+
+    .swBox2 {
+      height: 100%;
+      padding-top: 30px;
+    }
+  }
+}

+ 127 - 0
pc/src/pages/A2Main/index.tsx

@@ -0,0 +1,127 @@
+import React, { useCallback, useState } from "react";
+import styles from "./index.module.scss";
+import LogoImg from "@/assets/img/logo.png";
+import classNames from "classnames";
+import SwiperCom from "./SwiperCom";
+import VideoBox from "./VideoBox";
+import { A2SwType } from "@/types";
+
+const incoArr = [
+  {
+    id: 1,
+    data: [
+      {
+        id: 1,
+        name: "虎门销烟1-1",
+        path: "",
+        info: {
+          title: "视频66666",
+          txt: "撒大苏打撒旦111111111111111111111111111111111111111111撒大苏打撒旦撒大苏打撒旦撒大苏打撒旦撒大苏打撒旦撒大苏打撒旦撒大苏打撒旦撒大苏打撒旦撒大苏打撒旦撒大苏打撒旦撒大苏打撒旦撒大苏打撒旦撒大苏打撒旦撒大苏打撒旦撒大苏打撒旦11111",
+        },
+      },
+      {
+        id: 2,
+        name: "虎门销烟1-1",
+        path: "",
+        info: {
+          title: "视频66666",
+          txt: "撒大苏打撒旦11111111111111111111111111111111111111111111111",
+        },
+      },
+      {
+        id: 3,
+        name: "虎门销烟1-1",
+        path: "",
+        info: {
+          title: "视频66666",
+          txt: "撒大苏打撒旦11111111111111111111111111111111111111111111111",
+        },
+      },
+    ],
+  },
+  {
+    id: 2,
+    data: [
+      { id: 1, name: "虎门销烟2-111111111111111111111111111111", path: "" },
+      { id: 2, name: "虎门销烟2-1", path: "" },
+      { id: 3, name: "虎门销烟2-1", path: "" },
+      { id: 4, name: "虎门销烟2-111111111111111111111111111111", path: "" },
+      { id: 5, name: "虎门销烟2-1", path: "" },
+      { id: 6, name: "虎门销烟2-1", path: "" },
+      { id: 7, name: "虎门销烟2-111111111111111111111111111111", path: "" },
+      { id: 8, name: "虎门销烟2-1", path: "" },
+      { id: 9, name: "虎门销烟2-1", path: "" },
+    ],
+  },
+  {
+    id: 3,
+    data: [
+      { id: 1, name: "虎门销烟3-1", path: "" },
+      { id: 2, name: "虎门销烟3-1", path: "" },
+      { id: 3, name: "虎门销烟3-1", path: "" },
+    ],
+  },
+  { id: 4 },
+  { id: 5 },
+];
+
+function A2Main() {
+  // 传给轮播图的数据
+  const [swData, setSwData] = useState<A2SwType[]>([]);
+
+  // 底部选中的状态
+  const [type, setType] = useState(0);
+  const typeChangeFu = useCallback((item: any) => {
+    setSwData(item.data);
+    setType(item.id);
+  }, []);
+
+  return (
+    <div className={styles.A2Main}>
+      {/* 左上方logo */}
+      <div className="logo">
+        <img src={LogoImg} alt="" />
+      </div>
+      {/* 底部轮播图 */}
+      <div
+        className={classNames(
+          "swBox",
+          [1, 2, 3].includes(type) ? "swBox1" : "",
+          [4, 5].includes(type) ? "swBox2" : ""
+        )}
+      >
+        <div className="swBoxMain">
+          <div className="top">
+            {incoArr.map((v) => (
+              <div
+                onClick={() => typeChangeFu(v)}
+                className={classNames(
+                  "row",
+                  `row${v.id}`,
+                  type === v.id ? `rowAc${v.id}` : ""
+                )}
+                key={v.id}
+              ></div>
+            ))}
+            {/* 展开收起按钮 */}
+            <div
+              className={classNames("openIcon")}
+              hidden={!type}
+              onClick={() => setType(0)}
+            ></div>
+          </div>
+          {/* 轮播图主体 */}
+          {[1, 2, 3].includes(type) ? (
+            <SwiperCom type={type} data={swData} />
+          ) : null}
+        </div>
+      </div>
+      {/* 历史播放视频 */}
+      <VideoBox />
+    </div>
+  );
+}
+
+const MemoA2Main = React.memo(A2Main);
+
+export default MemoA2Main;

+ 24 - 0
pc/src/store/reducer/A2Main.ts

@@ -0,0 +1,24 @@
+import { A2VideoType } from "@/types";
+
+// 初始化状态
+const initState = {
+  // 历史查看视频
+  videoInfo: {
+    id: 0,
+    title: "",
+    txt: "",
+  },
+};
+
+// 定义 action 类型
+type Props = { type: "main/lookVideo"; payload: A2VideoType };
+
+// 频道 reducer
+export default function loginReducer(state = initState, action: Props) {
+  switch (action.type) {
+    case "main/lookVideo":
+      return { ...state, videoInfo: action.payload };
+    default:
+      return state;
+  }
+}

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

@@ -3,10 +3,12 @@ import { combineReducers } from "redux";
 
 // 导入 登录 模块的 reducer
 import A0layout from "./layout";
+import A2Main from "./A2Main";
 
 // 合并 reducer
 const rootReducer = combineReducers({
   A0layout,
+  A2Main
 });
 
 // 默认导出

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

@@ -1 +1,2 @@
 
+export * from './store/A2Main'

+ 12 - 0
pc/src/types/store/A2Main.d.ts

@@ -0,0 +1,12 @@
+export type A2SwType ={
+  id:number
+  name:string
+  path:string
+  info?:{ title: string, txt: string }
+}
+
+export type A2VideoType = {
+  id: number;
+  title: string;
+  txt: string;
+}

+ 3 - 1
pc/src/utils/history.ts

@@ -17,4 +17,6 @@ export const urlParameter = (data: string) => {
     });
     return params;
   } else return {};
-};
+};
+
+export const envUrl = window.location.origin