shaogen1995 2 gadi atpakaļ
revīzija
35ec6a54f1
51 mainītis faili ar 31150 papildinājumiem un 0 dzēšanām
  1. 23 0
      pc/.gitignore
  2. 46 0
      pc/README.md
  3. 10 0
      pc/config-overrides.js
  4. 29760 0
      pc/package-lock.json
  5. 58 0
      pc/package.json
  6. 8 0
      pc/path.tsconfig.json
  7. BIN
      pc/public/favicon.ico
  8. 43 0
      pc/public/index.html
  9. 56 0
      pc/src/App.tsx
  10. BIN
      pc/src/assets/img/home/Group.png
  11. BIN
      pc/src/assets/img/home/Ldian.png
  12. BIN
      pc/src/assets/img/home/bg-home.jpg
  13. BIN
      pc/src/assets/img/home/icon-close.png
  14. BIN
      pc/src/assets/img/home/icon-down.png
  15. BIN
      pc/src/assets/img/home/icon-up.png
  16. BIN
      pc/src/assets/img/home/icon-xuanze.png
  17. BIN
      pc/src/assets/img/home/infoBac.jpg
  18. BIN
      pc/src/assets/img/home/lingxing.png
  19. BIN
      pc/src/assets/img/home/scene1.jpg
  20. BIN
      pc/src/assets/img/home/scene2.jpg
  21. BIN
      pc/src/assets/img/home/scene3.jpg
  22. BIN
      pc/src/assets/img/home/scene4.jpg
  23. BIN
      pc/src/assets/img/home/title-home.png
  24. BIN
      pc/src/assets/img/home/top1.png
  25. BIN
      pc/src/assets/img/home/top2.png
  26. BIN
      pc/src/assets/img/home/top3.png
  27. BIN
      pc/src/assets/img/home/top4.png
  28. 100 0
      pc/src/assets/styles/base.css
  29. 123 0
      pc/src/assets/styles/base.less
  30. 29 0
      pc/src/components/Message/index.tsx
  31. 28 0
      pc/src/components/NotFound/index.tsx
  32. 10 0
      pc/src/components/SpinLoding/index.module.scss
  33. 13 0
      pc/src/components/SpinLoding/index.tsx
  34. 39 0
      pc/src/index.tsx
  35. 338 0
      pc/src/pages/A1_Home/index.module.scss
  36. 161 0
      pc/src/pages/A1_Home/index.tsx
  37. 6 0
      pc/src/pages/A2_Goods/index.module.scss
  38. 14 0
      pc/src/pages/A2_Goods/index.tsx
  39. 5 0
      pc/src/pages/初始化组件/index.module.scss
  40. 14 0
      pc/src/pages/初始化组件/index.tsx
  41. 20 0
      pc/src/store/index.ts
  42. 13 0
      pc/src/store/reducer/index.ts
  43. 34 0
      pc/src/store/reducer/layout.ts
  44. 5 0
      pc/src/types/declaration.d.ts
  45. 2 0
      pc/src/types/index.d.ts
  46. 4 0
      pc/src/types/store/login.d.ts
  47. 11 0
      pc/src/utils/domShow.ts
  48. 22 0
      pc/src/utils/history.ts
  49. 78 0
      pc/src/utils/http.ts
  50. 50 0
      pc/src/utils/message.ts
  51. 27 0
      pc/tsconfig.json

+ 23 - 0
pc/.gitignore

@@ -0,0 +1,23 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# production
+/build
+
+# misc
+.DS_Store
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*

+ 46 - 0
pc/README.md

@@ -0,0 +1,46 @@
+# Getting Started with Create React App
+
+This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
+
+## Available Scripts
+
+In the project directory, you can run:
+
+### `npm start`
+
+Runs the app in the development mode.\
+Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
+
+The page will reload if you make edits.\
+You will also see any lint errors in the console.
+
+### `npm test`
+
+Launches the test runner in the interactive watch mode.\
+See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
+
+### `npm run build`
+
+Builds the app for production to the `build` folder.\
+It correctly bundles React in production mode and optimizes the build for the best performance.
+
+The build is minified and the filenames include the hashes.\
+Your app is ready to be deployed!
+
+See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
+
+### `npm run eject`
+
+**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
+
+If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
+
+Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
+
+You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
+
+## Learn More
+
+You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
+
+To learn React, check out the [React documentation](https://reactjs.org/).

+ 10 - 0
pc/config-overrides.js

@@ -0,0 +1,10 @@
+const path = require('path')
+const { override, addWebpackAlias } = require('customize-cra')
+
+// 添加 @ 别名
+const webpackAlias = addWebpackAlias({
+  '@': path.resolve(__dirname, 'src'),
+})
+
+// 导出要进行覆盖的 webpack 配置
+module.exports = override(webpackAlias)

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 29760 - 0
pc/package-lock.json


+ 58 - 0
pc/package.json

@@ -0,0 +1,58 @@
+{
+  "name": "demo",
+  "version": "0.1.0",
+  "private": true,
+  "dependencies": {
+    "@testing-library/jest-dom": "^5.16.5",
+    "@testing-library/react": "^13.4.0",
+    "@testing-library/user-event": "^13.5.0",
+    "@types/jest": "^27.5.2",
+    "@types/node": "^16.18.3",
+    "@types/react": "^18.0.24",
+    "@types/react-dom": "^18.0.8",
+    "antd": "^5.4.7",
+    "axios": "^1.1.3",
+    "react": "^18.2.0",
+    "react-dom": "^18.2.0",
+    "react-redux": "^8.0.4",
+    "react-router-dom": "5.3",
+    "react-scripts": "5.0.1",
+    "redux": "^4.2.0",
+    "redux-devtools-extension": "^2.13.9",
+    "redux-thunk": "^2.4.1",
+    "sass": "^1.55.0",
+    "typescript": "^4.8.4",
+    "web-vitals": "^2.1.4"
+  },
+  "scripts": {
+    "dev": "react-app-rewired start",
+    "build": "react-app-rewired build",
+    "test": "react-app-rewired test",
+    "eject": "react-scripts eject"
+  },
+  "eslintConfig": {
+    "extends": [
+      "react-app",
+      "react-app/jest"
+    ]
+  },
+  "browserslist": {
+    "production": [
+      ">0.2%",
+      "not dead",
+      "not op_mini all"
+    ],
+    "development": [
+      "last 1 chrome version",
+      "last 1 firefox version",
+      "last 1 safari version"
+    ]
+  },
+  "devDependencies": {
+    "@types/history": "^5.0.0",
+    "@types/react-router-dom": "^5.3.3",
+    "customize-cra": "^1.0.0",
+    "react-app-rewired": "^2.2.1"
+  },
+  "homepage": "."
+}

+ 8 - 0
pc/path.tsconfig.json

@@ -0,0 +1,8 @@
+{
+    "compilerOptions": {
+      "baseUrl": "./",
+      "paths": {
+        "@/*": ["src/*"]
+      }
+    }
+  }

BIN
pc/public/favicon.ico


+ 43 - 0
pc/public/index.html

@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html lang="zh">
+  <head>
+    <meta charset="utf-8" />
+    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
+    <meta name="viewport" content="width=device-width, initial-scale=1" />
+    <meta name="theme-color" content="#000000" />
+    <meta
+      name="description"
+      content="Web site created using create-react-app"
+    />
+    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
+    <!--
+      manifest.json provides metadata used when your web app is installed on a
+      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
+    -->
+
+    <!--
+      Notice the use of %PUBLIC_URL% in the tags above.
+      It will be replaced with the URL of the `public` folder during the build.
+      Only files inside the `public` folder can be referenced from the HTML.
+
+      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
+      work correctly both with client-side routing and a non-root public URL.
+      Learn how to configure a non-root public URL by running `npm run build`.
+    -->
+    <title>React App</title>
+  </head>
+  <body>
+    <noscript>You need to enable JavaScript to run this app.</noscript>
+    <div id="root"></div>
+    <!--
+      This HTML file is a template.
+      If you open it directly in the browser, you will see an empty page.
+
+      You can add webfonts, meta tags, or analytics to this file.
+      The build step will place the bundled scripts into the <body> tag.
+
+      To begin the development, run `npm start` or `yarn start`.
+      To create a production bundle, use `npm run build` or `yarn build`.
+    -->
+  </body>
+</html>

+ 56 - 0
pc/src/App.tsx

@@ -0,0 +1,56 @@
+import "@/assets/styles/base.css";
+import React from "react";
+import { Router, Route, Switch } from "react-router-dom";
+import history from "./utils/history";
+import SpinLoding from "./components/SpinLoding";
+import { Image } from "antd";
+import MessageCom from "./components/Message";
+import store, { RootState } from "./store";
+import { useSelector } from "react-redux";
+import NotFound from "./components/NotFound";
+
+const Home = React.lazy(() => import("./pages/A1_Home"));
+const Goods = React.lazy(() => import("./pages/A2_Goods"));
+
+function App() {
+  // 从仓库中获取查看图片的信息
+  const lookBigImg = useSelector(
+    (state: RootState) => state.A0layout.lookBigImg
+  );
+  return (
+    <div id="app">
+      <Router history={history}>
+        <React.Suspense fallback={<SpinLoding />}>
+          <Switch>
+            <Route exact path="/" component={Home} />
+            <Route exact path="/goods" component={Goods} />
+            {/* 找不到页面 */}
+            <Route path="*" component={NotFound} />
+          </Switch>
+        </React.Suspense>
+      </Router>
+
+      {/* 所有图片点击预览查看大图 */}
+      <Image
+        preview={{
+          visible: lookBigImg.show,
+          src: lookBigImg.url,
+          onVisibleChange: (value) => {
+            // 清除仓库信息
+            store.dispatch({
+              type: "layout/lookBigImg",
+              payload: { url: "", show: false },
+            });
+          },
+        }}
+      />
+
+      {/* antd 轻提示 ---兼容360浏览器 */}
+      <MessageCom />
+    </div>
+  );
+}
+
+const MemoApp = React.memo(App);
+
+export default MemoApp;

BIN
pc/src/assets/img/home/Group.png


BIN
pc/src/assets/img/home/Ldian.png


BIN
pc/src/assets/img/home/bg-home.jpg


BIN
pc/src/assets/img/home/icon-close.png


BIN
pc/src/assets/img/home/icon-down.png


BIN
pc/src/assets/img/home/icon-up.png


BIN
pc/src/assets/img/home/icon-xuanze.png


BIN
pc/src/assets/img/home/infoBac.jpg


BIN
pc/src/assets/img/home/lingxing.png


BIN
pc/src/assets/img/home/scene1.jpg


BIN
pc/src/assets/img/home/scene2.jpg


BIN
pc/src/assets/img/home/scene3.jpg


BIN
pc/src/assets/img/home/scene4.jpg


BIN
pc/src/assets/img/home/title-home.png


BIN
pc/src/assets/img/home/top1.png


BIN
pc/src/assets/img/home/top2.png


BIN
pc/src/assets/img/home/top3.png


BIN
pc/src/assets/img/home/top4.png


+ 100 - 0
pc/src/assets/styles/base.css

@@ -0,0 +1,100 @@
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+}
+html {
+  height: 100%;
+  font-size: 14px;
+  user-select: none;
+}
+body {
+  font: 1em/1.4 'Microsoft Yahei', 'PingFang SC', 'Avenir', 'Segoe UI', 'Hiragino Sans GB', 'STHeiti', 'Microsoft Sans Serif', 'WenQuanYi Micro Hei', sans-serif;
+  height: 100%;
+  color: #333;
+}
+a {
+  text-decoration: none;
+  color: #333;
+  outline: none;
+}
+i {
+  font-style: normal;
+}
+img {
+  max-width: 100%;
+  max-height: 100%;
+  vertical-align: middle;
+  object-fit: cover;
+}
+ul {
+  list-style: none;
+}
+body {
+  overflow: auto;
+  overflow-y: overlay;
+}
+/* 文本域取消下拉 */
+textarea {
+  resize: none !important;
+}
+/* 主题色 */
+:root {
+  --themeColor: #A33328;
+}
+[hidden] {
+  display: none !important;
+}
+/* 找不到页面 */
+.noFindPage {
+  opacity: 0;
+  transition: opacity 0.5s;
+}
+.noFindPage .noFindBtn {
+  text-align: center;
+}
+/* 兼容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: auto;
+  overflow-y: overlay;
+}
+#root a {
+  color: var(--themeColor);
+}
+#root #app {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+}
+#root #app > div {
+  width: 100%;
+  height: 100%;
+}
+#root .myscroll::-webkit-scrollbar {
+  /*滚动条整体样式*/
+  width: 3px;
+  /*高宽分别对应横竖滚动条的尺寸*/
+  height: 1px;
+}
+#root .myscroll::-webkit-scrollbar-thumb {
+  /*滚动条里面小方块*/
+  border-radius: 10px;
+  -webkit-box-shadow: inset 0 0 5px transparent;
+  background: var(--themeColor);
+}
+#root .myscroll::-webkit-scrollbar-track {
+  /*滚动条里面轨道*/
+  -webkit-box-shadow: inset 0 0 5px transparent;
+  border-radius: 10px;
+  background: transparent;
+}

+ 123 - 0
pc/src/assets/styles/base.less

@@ -0,0 +1,123 @@
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+}
+
+html {
+  height: 100%;
+  font-size: 14px;
+  user-select: none;
+}
+
+body {
+  font: 1em/1.4 'Microsoft Yahei', 'PingFang SC', 'Avenir', 'Segoe UI', 'Hiragino Sans GB', 'STHeiti', 'Microsoft Sans Serif', 'WenQuanYi Micro Hei', sans-serif;
+  height: 100%;
+  color: #333;
+}
+
+a {
+  text-decoration: none;
+  color: #333;
+  outline: none;
+}
+
+i {
+  font-style: normal;
+}
+
+img {
+  max-width: 100%;
+  max-height: 100%;
+  vertical-align: middle;
+  object-fit: cover;
+}
+
+ul {
+  list-style: none;
+}
+
+body {
+  overflow: auto;
+  overflow-y: overlay;
+}
+
+/* 文本域取消下拉 */
+textarea {
+  resize: none !important;
+}
+
+/* 主题色 */
+:root {
+  --themeColor: #A33328;
+}
+
+
+
+[hidden] {
+  display: none !important;
+}
+
+/* 找不到页面 */
+.noFindPage {
+  opacity: 0;
+  transition: opacity .5s;
+
+  .noFindBtn {
+    text-align: center;
+  }
+}
+
+/* 兼容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: auto;
+  overflow-y: overlay;
+
+  a {
+    color: var(--themeColor);
+  }
+
+  #app {
+    width: 100%;
+    height: 100%;
+    overflow: hidden;
+
+    &>div {
+      width: 100%;
+      height: 100%;
+    }
+  }
+
+  .myscroll::-webkit-scrollbar {
+    /*滚动条整体样式*/
+    width: 3px;
+    /*高宽分别对应横竖滚动条的尺寸*/
+    height: 1px;
+  }
+
+  .myscroll::-webkit-scrollbar-thumb {
+    /*滚动条里面小方块*/
+    border-radius: 10px;
+    -webkit-box-shadow: inset 0 0 5px transparent;
+    background: var(--themeColor);
+  }
+
+  .myscroll::-webkit-scrollbar-track {
+    /*滚动条里面轨道*/
+    -webkit-box-shadow: inset 0 0 5px transparent;
+    border-radius: 10px;
+    background: transparent;
+  }
+}

+ 29 - 0
pc/src/components/Message/index.tsx

@@ -0,0 +1,29 @@
+import React, { useEffect } from "react";
+import { message } from "antd";
+import { useSelector } from "react-redux";
+import { RootState } from "@/store";
+
+function MessageCom() {
+  // 从仓库中获取 antd 轻提示信息
+  const messageReducerInfo = useSelector(
+    (state: RootState) => state.A0layout.message
+  );
+
+  const [messageApi, contextHolder] = message.useMessage();
+
+  useEffect(() => {
+    if (messageReducerInfo.txt) {
+      messageApi.open({
+        type: messageReducerInfo.type,
+        content: messageReducerInfo.txt,
+        duration: messageReducerInfo.duration,
+      });
+    }
+  }, [messageApi, messageReducerInfo]);
+
+  return <>{contextHolder}</>;
+}
+
+const MemoMessage = React.memo(MessageCom);
+
+export default MemoMessage;

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

@@ -0,0 +1,28 @@
+import history from "@/utils/history";
+import { Button, 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 className="noFindBtn">
+        <Button type="primary" onClick={() => history.replace("/")}>
+          去首页
+        </Button>
+      </div>
+    </div>
+  );
+}

+ 10 - 0
pc/src/components/SpinLoding/index.module.scss

@@ -0,0 +1,10 @@
+.SpinLoding {
+  position: relative;
+  z-index: 9999;
+  width: 100%;
+  height: 100%;
+  background-color: #fff;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}

+ 13 - 0
pc/src/components/SpinLoding/index.tsx

@@ -0,0 +1,13 @@
+import styles from "./index.module.scss";
+import { Spin } from "antd";
+import React from "react";
+function SpinLoding() {
+  return (
+    <div className={styles.SpinLoding}>
+      <Spin size='large'/>
+    </div>
+  );
+}
+const MemoSpinLoding = React.memo(SpinLoding);
+
+export default MemoSpinLoding;

+ 39 - 0
pc/src/index.tsx

@@ -0,0 +1,39 @@
+import App from "./App";
+import store from "./store/index";
+import { Provider } from "react-redux";
+import { createRoot } from "react-dom/client";
+
+import { ConfigProvider } from "antd";
+
+// 兼容360浏览器
+import {
+  StyleProvider,
+  legacyLogicalPropertiesTransformer,
+} from "@ant-design/cssinjs";
+
+import "dayjs/locale/zh-cn";
+import locale from "antd/locale/zh_CN";
+
+const container = document.getElementById("root") as HTMLElement;
+
+const root = createRoot(container);
+
+root.render(
+  <ConfigProvider
+    locale={locale}
+    theme={{
+      token: {
+        colorPrimary: "#A33328",
+      },
+    }}
+  >
+    <Provider store={store}>
+      <StyleProvider
+        hashPriority="high"
+        transformers={[legacyLogicalPropertiesTransformer]}
+      >
+        <App />
+      </StyleProvider>
+    </Provider>
+  </ConfigProvider>
+);

+ 338 - 0
pc/src/pages/A1_Home/index.module.scss

@@ -0,0 +1,338 @@
+.A1_Home {
+  background-image: url('../../assets/img/home/bg-home.jpg');
+  background-size: 100% 100%;
+  position: relative;
+
+  :global {
+    .homeLogo {
+      position: absolute;
+      top: 110px;
+      left: 80px;
+      z-index: 1;
+    }
+
+    .homeFloo {
+      position: absolute;
+      bottom: 50px;
+      left: 0;
+      width: 100%;
+      z-index: 1;
+      display: flex;
+      justify-content: center;
+
+      .homeFlooRow {
+        cursor: pointer;
+        width: 180px;
+        height: 56px;
+        background-image: url('../../assets/img/home/icon-xuanze.png');
+        background-size: 100% 100%;
+        margin-left: 130px;
+        position: relative;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        font-size: 20px;
+        color: var(--themeColor);
+
+        &::before {
+          pointer-events: none;
+          content: '';
+          position: absolute;
+          top: 50%;
+          transform: translateY(-50%);
+          right: -90px;
+          width: 57px;
+          height: 14px;
+          background-image: url('../../assets/img/home/lingxing.png');
+          background-size: 100% 100%;
+        }
+
+        &:nth-of-type(1) {
+          margin-left: 0;
+
+          &::after {
+            pointer-events: none;
+            content: '';
+            position: absolute;
+            top: 50%;
+            transform: translateY(-50%);
+            left: -90px;
+            width: 57px;
+            height: 14px;
+            background-image: url('../../assets/img/home/lingxing.png');
+            background-size: 100% 100%;
+          }
+        }
+      }
+    }
+
+    .homeShowIcon {
+      position: absolute;
+      bottom: 140px;
+      left: 50%;
+      transform: translateX(-50%);
+      cursor: pointer;
+      width: 50px;
+      height: 50px;
+      background-image: url('../../assets/img/home/icon-up.png');
+      background-size: 100% 100%;
+    }
+
+    .homeInfoBox {
+      position: absolute;
+      z-index: 2;
+      width: 100%;
+      height: 100%;
+      top: 1000px;
+      left: 0;
+      background-color: rgba(255, 255, 255, .6);
+      backdrop-filter: blur(20px);
+      transition: all .5s;
+      padding: 80px 160px 120px;
+
+      .homeInfoTop {
+        width: 100%;
+        height: 270px;
+        margin-bottom: 60px;
+        display: flex;
+        justify-content: space-between;
+
+        .homeInfoTopRow {
+          width: 23%;
+          border-radius: 8px;
+
+          .homeInfoTopRowSon {
+            cursor: pointer;
+            width: 100%;
+            height: 100%;
+            border-radius: 8px;
+            overflow: hidden;
+
+            &>div {
+              width: 100%;
+              height: 100%;
+              background-size: 100% 100%;
+              transition: all .3s;
+
+            }
+
+            .sonImg1 {
+              background-image: url('../../assets/img/home/top1.png');
+            }
+
+            .sonImg2 {
+              background-image: url('../../assets/img/home/top2.png');
+            }
+
+            .sonImg3 {
+              background-image: url('../../assets/img/home/top3.png');
+            }
+
+            .sonImg4 {
+              background-image: url('../../assets/img/home/top4.png');
+            }
+
+            &:hover {
+              &>div {
+                transform: scale(1.05);
+              }
+            }
+          }
+
+
+        }
+
+
+      }
+
+      .homeInfoTxt {
+        width: 100%;
+        height: calc(100% - 380px);
+        display: flex;
+
+        .homeInfoTxtLL {
+          width: 48%;
+          margin-right: 2%;
+          height: 100%;
+
+          .homeTxtTitle {
+            font-size: 30px;
+            font-weight: 700;
+            color: var(--themeColor);
+            padding-left: 40px;
+            position: relative;
+            margin-bottom: 20px;
+
+            &::before {
+              content: '';
+              position: absolute;
+              width: 15px;
+              height: 15px;
+              left: 0;
+              top: 50%;
+              transform: translateY(-50%);
+              background-image: url('../../assets/img/home/Ldian.png');
+              background-size: 100% 100%;
+            }
+          }
+
+          .homeTxtMain {
+            width: 100%;
+            height: calc(100% - 60px);
+            padding-right: 30px;
+            overflow-y: auto;
+            font-size: 14px;
+            line-height: 24px;
+
+            &>p {
+              margin-bottom: 30px;
+
+              &:last-child {
+                margin-bottom: 0;
+              }
+            }
+          }
+        }
+
+        .homeInfoTxtRR {
+          width: 50%;
+          height: 100%;
+          background-image: url('../../assets/img/home/infoBac.jpg');
+          background-size: 100% 100%;
+          border-radius: 10px;
+        }
+      }
+
+      .hideInfoIcon {
+        position: absolute;
+        bottom: 60px;
+        left: 50%;
+        transform: translateX(-50%);
+        cursor: pointer;
+        width: 50px;
+        height: 50px;
+        background-image: url('../../assets/img/home/icon-down.png');
+        background-size: 100% 100%;
+      }
+    }
+
+    .homeInfoBoxAc {
+      top: 0;
+    }
+
+    .homeSceneBox {
+      opacity: 0;
+      pointer-events: none;
+      position: absolute;
+      z-index: 3;
+      top: 0;
+      left: 0;
+      width: 100%;
+      height: 100%;
+      background-color: rgba(255, 255, 255, .6);
+      backdrop-filter: blur(20px);
+      transition: all .3s;
+      padding: 0 120px;
+
+      .homeSceneClose {
+        position: absolute;
+        top: 40px;
+        right: 30px;
+        width: 50px;
+        height: 50px;
+        cursor: pointer;
+        background-image: url('../../assets/img/home/icon-close.png');
+        background-size: 100% 100%;
+      }
+
+      .homeSceneTit {
+        margin: 70px 0 40px;
+        text-align: center;
+      }
+
+      .homeSceneList {
+        display: flex;
+        justify-content: space-between;
+
+        .sceneRow {
+          cursor: pointer;
+          width: 23%;
+          height: 270px;
+          display: flex;
+          justify-content: center;
+          align-items: center;
+
+          &>div {
+            width: 90%;
+            height: 90%;
+            background-size: cover;
+            position: relative;
+            transition: all .3s;
+
+            &>p {
+              font-weight: 700;
+              transition: all .3s;
+              pointer-events: none;
+              position: absolute;
+              bottom: -60px;
+              width: 100%;
+              text-align: center;
+              font-size: 16px;
+            }
+          }
+
+          &:hover {
+            &>div {
+              width: 100%;
+              height: 100%;
+
+              &>p {
+                color: var(--themeColor);
+              }
+            }
+          }
+
+
+
+          .sceneRowImg1 {
+            background-image: url('../../assets/img/home/scene1.jpg');
+
+          }
+
+          .sceneRowImg2 {
+            background-image: url('../../assets/img/home/scene2.jpg');
+          }
+
+          .sceneRowImg3 {
+            background-image: url('../../assets/img/home/scene3.jpg');
+          }
+
+          .sceneRowImg4 {
+            background-image: url('../../assets/img/home/scene4.jpg');
+          }
+
+
+
+        }
+
+        .sceneRowAc {
+          &>div {
+            width: 100%;
+            height: 100%;
+
+            &>p {
+              color: var(--themeColor);
+            }
+          }
+        }
+
+      }
+    }
+
+    .homeSceneBoxAc {
+      opacity: 1;
+      pointer-events: auto;
+    }
+
+  }
+}

+ 161 - 0
pc/src/pages/A1_Home/index.tsx

@@ -0,0 +1,161 @@
+import React, { useCallback, useEffect, useState } from "react";
+import styles from "./index.module.scss";
+import { MessageFu } from "@/utils/message";
+import history from "@/utils/history";
+import classNames from "classnames";
+import logoImg from "@/assets/img/home/title-home.png";
+import sceneTitImg from "@/assets/img/home/Group.png";
+
+const arr = [
+  { id: 1, name: "线上展厅" },
+  { id: 2, name: "建筑航拍" },
+  { id: 3, name: "遗址漫游" },
+  { id: 4, name: "馆藏鉴赏" },
+];
+
+const sceneArr = [
+  {
+    id: 1,
+    name: "文物厅",
+    path: "https://houseoss.4dkankan.com/project/jsswlt/index.html#/?m=1291",
+  },
+  {
+    id: 2,
+    name: "书法厅",
+    path: "https://houseoss.4dkankan.com/project/jsswlt/index.html#/?m=1291",
+  },
+  {
+    id: 3,
+    name: "仡佬族文化厅",
+    path: "https://houseoss.4dkankan.com/project/jsswlt/index.html#/?m=1291",
+  },
+  {
+    id: 4,
+    name: "30周年成就展",
+    path: "https://houseoss.4dkankan.com/project/jsswlt/index.html#/?m=1291",
+  },
+];
+
+function A1_Home() {
+  // 线上展厅
+  const [scene, setScene] = useState(false);
+  const [sceneInd, setSceneInd] = useState(0);
+
+  useEffect(() => {
+    setSceneInd(0);
+  }, [scene]);
+
+  // 点击下面的4个按钮
+  const cutTabFu = useCallback((id: number) => {
+    if (id === 1) setScene(true);
+    else if (id === 2)
+      window.open(
+        "https://zzbbh.4dage.com/SWKK/show.html?id=WK1655789833349554176&vr=fd720_oOB3GPSeh"
+      );
+    else if (id === 3)
+      window.open(
+        "https://www.4dkankan.com/panorama/show.html?id=WK1655790008340111360&vr=fd720_kNC4eKj3U&lang=zh"
+      );
+    else if (id === 4) history.push("/goods");
+  }, []);
+
+  // 展开详情
+  const [show, setShow] = useState(false);
+
+  // 点击线上展厅页面
+  const sceneClickFu = useCallback((id: number, path: string) => {
+    setSceneInd(id);
+    window.open(path);
+  }, []);
+
+  return (
+    <div className={styles.A1_Home}>
+      {/* logo */}
+      <div className="homeLogo">
+        <img src={logoImg} alt="" />
+      </div>
+      {/* 底部导航 */}
+      <div className="homeFloo">
+        {arr.map((v) => (
+          <div
+            onClick={() => cutTabFu(v.id)}
+            className="homeFlooRow"
+            key={v.id}
+          >
+            {v.name}
+          </div>
+        ))}
+      </div>
+
+      {/* 展开按钮 */}
+      <div className="homeShowIcon" onClick={() => setShow(true)}></div>
+
+      {/* 展开的详情 */}
+      <div className={classNames("homeInfoBox", show ? "homeInfoBoxAc" : "")}>
+        {/* 顶部4个title */}
+        <div className="homeInfoTop">
+          {arr.map((v) => (
+            <div className="homeInfoTopRow" key={v.id}>
+              <div className="homeInfoTopRowSon" onClick={() => cutTabFu(v.id)}>
+                <div className={`sonImg${v.id}`}></div>
+              </div>
+            </div>
+          ))}
+        </div>
+        {/* 关于我们 */}
+        <div className="homeInfoTxt">
+          <div className="homeInfoTxtLL">
+            <div className="homeTxtTitle">关于我们</div>
+            <div className="homeTxtMain myscroll">
+              <p>
+                仡佬族是最早开辟贵州土地的民族,是贵州高原的“地盘业主,古老前人。”。务川自治县是仡佬民族的发源地,早在殷商时期,仡佬族的先人们就在这片神奇的土地上采砂炼丹、繁衍生息,留下了厚重的仡佬文化和丹砂文化历史。今天记者将带大家走进务川仡佬民族文化博物馆,听文物讲述民族文化。
+              </p>
+              <p>
+                务川仡佬民族文化博物馆讲解员付芳向我们一一介绍着,“这是我们博物馆一件比较有意义的文物,它叫陶辟邪摇钱树座,被考古专家发现之后,一片片的筛选出来,共有105片碎片,一片片拼装上去之后,才发现是一座精美的陶辟邪摇钱树座。”
+              </p>
+              <p>
+                “接下来我带你们看一下我们馆的国家二级文物,穿索钱串,它的价值并不在于钱币的本身,而在于这根棕绳但是这根棕绳保存得比较完好,说明这根棕绳的价值远远大于钱币,所以被定为国家二级文物。”
+              </p>
+            </div>
+          </div>
+          <div className="homeInfoTxtRR"></div>
+        </div>
+        {/* 收起按钮 */}
+        <div className="hideInfoIcon" onClick={() => setShow(false)}></div>
+      </div>
+
+      {/* 点击线上展厅之后出来的界面 */}
+      <div
+        className={classNames("homeSceneBox", scene ? "homeSceneBoxAc" : "")}
+      >
+        {/* 关闭按钮 */}
+        <div className="homeSceneClose" onClick={() => setScene(false)}></div>
+        {/* 线上展厅图片 */}
+        <div className="homeSceneTit">
+          <img src={sceneTitImg} alt="" />
+        </div>
+        {/* 线上展厅列表 */}
+        <div className="homeSceneList">
+          {sceneArr.map((v) => (
+            <div
+              onClick={() => sceneClickFu(v.id, v.path)}
+              className={classNames(
+                "sceneRow",
+                sceneInd === v.id ? "sceneRowAc" : ""
+              )}
+              key={v.id}
+            >
+              <div className={`sceneRowImg${v.id}`}>
+                <p>{v.name}</p>
+              </div>
+            </div>
+          ))}
+        </div>
+      </div>
+    </div>
+  );
+}
+
+const MemoA1_Home = React.memo(A1_Home);
+
+export default MemoA1_Home;

+ 6 - 0
pc/src/pages/A2_Goods/index.module.scss

@@ -0,0 +1,6 @@
+.A2_Goods{
+  
+  :global{
+    
+  }
+}

+ 14 - 0
pc/src/pages/A2_Goods/index.tsx

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

+ 5 - 0
pc/src/pages/初始化组件/index.module.scss

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

+ 14 - 0
pc/src/pages/初始化组件/index.tsx

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

+ 20 - 0
pc/src/store/index.ts

@@ -0,0 +1,20 @@
+// 导入 redux
+import { applyMiddleware, legacy_createStore as createStore } from 'redux'
+// 导入自己封装的  rootReducer 
+import rootReducer from './reducer'
+// 导入调试工具和 异步的 redux(用来发送异步请求)
+// 调试工具需要下载谷歌 扩展程序 我用的是 Redux DevTools 3.0.17
+import { composeWithDevTools } from 'redux-devtools-extension'
+import thunk from 'redux-thunk'
+
+// 创建仓库实例
+const store = createStore(rootReducer, composeWithDevTools(applyMiddleware(thunk)))
+
+// 声明 RootState,在使用仓库的时候用来使用
+export type RootState = ReturnType<typeof store.getState>
+
+// 声明 AppDispatch,在异步请求的时候来使用
+export type AppDispatch = typeof store.dispatch
+
+// 导出仓库实例
+export default store

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

@@ -0,0 +1,13 @@
+// 导入合并reducer的依赖
+import { combineReducers } from "redux";
+
+// 导入 登录 模块的 reducer
+import A0layout from "./layout";
+
+// 合并 reducer
+const rootReducer = combineReducers({
+  A0layout,
+});
+
+// 默认导出
+export default rootReducer;

+ 34 - 0
pc/src/store/reducer/layout.ts

@@ -0,0 +1,34 @@
+import { MessageType } from "@/utils/message";
+
+// 初始化状态
+const initState = {
+  // antd轻提示(兼容360浏览器)
+  message: {
+    txt: "",
+    type: "info",
+    duration: 3,
+  } as MessageType,
+  // 所有图片点击预览查看大图
+  lookBigImg: {
+    url: "",
+    show: false,
+  },
+};
+
+// 定义 action 类型
+type Props =
+  | { type: "layout/message"; payload: MessageType }
+  | { type: "layout/lookBigImg"; payload: { url: string; show: boolean } };
+// 频道 reducer
+export default function loginReducer(state = initState, action: Props) {
+  switch (action.type) {
+    // antd轻提示(兼容360浏览器)
+    case "layout/message":
+      return { ...state, message: action.payload };
+    // 所有图片点击预览查看大图
+    case "layout/lookBigImg":
+      return { ...state, lookBigImg: action.payload };
+    default:
+      return state;
+  }
+}

+ 5 - 0
pc/src/types/declaration.d.ts

@@ -0,0 +1,5 @@
+declare module "history";
+declare module "*.scss";
+declare module "*.png";
+declare module "*.jpg";
+declare module "*.gif";

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

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

+ 4 - 0
pc/src/types/store/login.d.ts

@@ -0,0 +1,4 @@
+export type LoginType = {
+  num: number;
+  active: number;
+}

+ 11 - 0
pc/src/utils/domShow.ts

@@ -0,0 +1,11 @@
+// 加载和上传的盒子的显示隐藏
+export const domShowFu = (ele: string, val: boolean) => {
+  const dom: HTMLDivElement = document.querySelector(ele)!;
+  if (val) {
+    dom.style.opacity = "1";
+    dom.style.pointerEvents = "auto";
+  } else {
+    dom.style.opacity = "0";
+    dom.style.pointerEvents = "none";
+  }
+};

+ 22 - 0
pc/src/utils/history.ts

@@ -0,0 +1,22 @@
+// createBrowserHistory 和 createHashHistory。
+// 这里我们简单说一下 createBrowserHistory地址栏不带#; createHashHistory 带#
+// 根据公司要求自己选择,createBrowserHistory在项目上线的时候需要服务器映射等处理。
+import { createHashHistory  } from 'history'
+const history = createHashHistory()
+export default history
+
+export const urlParameter = (data: string) => {
+  if (data) {
+    const query = data.substring(data.indexOf("?") + 1);
+    const arr = query.split("&");
+    const params = {} as any;
+    arr.forEach((v) => {
+      const key = v.substring(0, v.indexOf("="));
+      const val = v.substring(v.indexOf("=") + 1);
+      params[key] = val;
+    });
+    return params;
+  } else return {};
+};
+
+export const envUrl = window.location.origin

+ 78 - 0
pc/src/utils/http.ts

@@ -0,0 +1,78 @@
+import axios from "axios";
+import { MessageFu } from "./message";
+import { domShowFu } from "./domShow";
+// 请求基地址
+export const baseURL =
+  // 线下的图片地址需要加上/api/
+  // process.env.NODE_ENV === "development"
+  //   ? "http://192.168.20.55:8041/api/"
+  //   : "";
+process.env.NODE_ENV === "development" ? "https://ypbwg.4dage.com" : "";
+
+// 处理  类型“AxiosResponse<any, any>”上不存在属性“code”
+declare module "axios" {
+  interface AxiosResponse {
+    code: number;
+    // 这里追加你的参数
+  }
+}
+
+// 创建 axios 实例
+const http = axios.create({
+  // --------线下的地址不用加/api/
+  // baseURL: baseURL,
+
+  // --------打包或线上环境接口需要加上api/
+  baseURL: baseURL + "/api/",
+  timeout: 5000,
+});
+
+let axajInd = 0;
+
+// 请求拦截器
+http.interceptors.request.use(
+  function (config: any) {
+    // 发请求前打开加载提示
+    domShowFu("#AsyncSpinLoding", true);
+
+    axajInd++;
+    return config;
+  },
+  function (err) {
+    return Promise.reject(err);
+  }
+);
+
+let timeId = -1;
+
+// 响应拦截器
+http.interceptors.response.use(
+  function (response) {
+    // 请求回来的关闭加载提示
+    axajInd--;
+    if (axajInd === 0) {
+      domShowFu("#AsyncSpinLoding", false);
+    }
+    if (response.data.code === 0) {
+      // MessageFu.success(response.data.msg);
+    } else MessageFu.warning(response.data.msg);
+
+    return response.data;
+  },
+  async function (err) {
+    clearTimeout(timeId);
+    timeId = window.setTimeout(() => {
+      axajInd = 0;
+      domShowFu("#AsyncSpinLoding", false);
+      // 如果因为网络原因,response没有,给提示消息
+      if (!err.response) {
+        MessageFu.error("网络繁忙,请稍后重试!");
+      } else MessageFu.error("响应错误,请联系管理员!");
+    }, 100);
+
+    return Promise.reject(err);
+  }
+);
+
+// 导出 axios 实例
+export default http;

+ 50 - 0
pc/src/utils/message.ts

@@ -0,0 +1,50 @@
+import store from "@/store";
+
+export type MessageType = {
+  txt: string;
+  type: "info" | "success" | "error" | "warning";
+  duration: number;
+};
+
+export const MessageFu = {
+  info: (txt: string, duration?: number) => {
+    store.dispatch({
+      type: "layout/message",
+      payload: {
+        txt,
+        type: "info",
+        duration: duration === undefined ? 3 : duration,
+      },
+    });
+  },
+  success: (txt: string, duration?: number) => {
+    store.dispatch({
+      type: "layout/message",
+      payload: {
+        txt,
+        type: "success",
+        duration: duration === undefined ? 3 : duration,
+      },
+    });
+  },
+  error: (txt: string, duration?: number) => {
+    store.dispatch({
+      type: "layout/message",
+      payload: {
+        txt,
+        type: "error",
+        duration: duration === undefined ? 3 : duration,
+      },
+    });
+  },
+  warning: (txt: string, duration?: number) => {
+    store.dispatch({
+      type: "layout/message",
+      payload: {
+        txt,
+        type: "warning",
+        duration: duration === undefined ? 3 : duration,
+      },
+    });
+  },
+};

+ 27 - 0
pc/tsconfig.json

@@ -0,0 +1,27 @@
+{
+  "extends": "./path.tsconfig.json",
+  "compilerOptions": {
+    "target": "es5",
+    "lib": [
+      "dom",
+      "dom.iterable",
+      "esnext"
+    ],
+    "allowJs": true,
+    "skipLibCheck": true,
+    "esModuleInterop": true,
+    "allowSyntheticDefaultImports": true,
+    "strict": true,
+    "forceConsistentCasingInFileNames": true,
+    "noFallthroughCasesInSwitch": true,
+    "module": "esnext",
+    "moduleResolution": "node",
+    "resolveJsonModule": true,
+    "isolatedModules": true,
+    "noEmit": true,
+    "jsx": "react-jsx"
+  },
+  "include": [
+    "src"
+  ]
+}