Ver código fonte

first commit

shaogen1995 9 meses atrás
commit
9dd84d4517
65 arquivos alterados com 43197 adições e 0 exclusões
  1. 12 0
      .editorconfig
  2. 24 0
      .gitignore
  3. 2 0
      .npmrc
  4. 11 0
      .prettierrc.js
  5. 39 0
      .vscode/settings.json
  6. 3 0
      README.md
  7. 10 0
      config-overrides.js
  8. 30270 0
      package-lock.json
  9. 65 0
      package.json
  10. 8 0
      path.tsconfig.json
  11. BIN
      public/favicon.png
  12. 43 0
      public/index.html
  13. 71 0
      public/info/index.js
  14. 18 0
      public/show.html
  15. 40 0
      src/App.tsx
  16. 55 0
      src/AppM.tsx
  17. BIN
      src/assets/img/IMGerror.png
  18. BIN
      src/assets/img/bg.jpg
  19. BIN
      src/assets/img/bgM.jpg
  20. BIN
      src/assets/img/bgm.mp3
  21. BIN
      src/assets/img/jiantou_w.png
  22. BIN
      src/assets/img/landtip.png
  23. BIN
      src/assets/img/loading.gif
  24. BIN
      src/assets/img/logo.png
  25. BIN
      src/assets/img/share.jpg
  26. BIN
      src/assets/img/top4.png
  27. 196 0
      src/assets/styles/base.css
  28. 246 0
      src/assets/styles/base.less
  29. 43 0
      src/assets/styles/iconfont/iconfont.css
  30. 1 0
      src/assets/styles/iconfont/iconfont.js
  31. 58 0
      src/assets/styles/iconfont/iconfont.json
  32. BIN
      src/assets/styles/iconfont/iconfont.ttf
  33. BIN
      src/assets/styles/iconfont/iconfont.woff
  34. BIN
      src/assets/styles/iconfont/iconfont.woff2
  35. 21 0
      src/components/AsyncSpinLoding/index.module.scss
  36. 15 0
      src/components/AsyncSpinLoding/index.tsx
  37. 16 0
      src/components/LazyImg/index.module.scss
  38. 22 0
      src/components/LazyImg/index.tsx
  39. 27 0
      src/components/Message/index.tsx
  40. 30 0
      src/components/NotFound/index.tsx
  41. 41 0
      src/components/RouterOrder.tsx
  42. 10 0
      src/components/SpinLoding/index.module.scss
  43. 13 0
      src/components/SpinLoding/index.tsx
  44. 37 0
      src/index.tsx
  45. 19 0
      src/pages/A1home/Bottom/data.ts
  46. 183 0
      src/pages/A1home/Bottom/index.module.scss
  47. 172 0
      src/pages/A1home/Bottom/index.tsx
  48. 67 0
      src/pages/A1home/Share/index.module.scss
  49. 51 0
      src/pages/A1home/Share/index.tsx
  50. 171 0
      src/pages/A1home/index.module.scss
  51. 116 0
      src/pages/A1home/index.tsx
  52. 5 0
      src/pages/初始化组件 copy/index.module.scss
  53. 14 0
      src/pages/初始化组件 copy/index.tsx
  54. 20 0
      src/store/index.ts
  55. 14 0
      src/store/reducer/index.ts
  56. 36 0
      src/store/reducer/layout.ts
  57. 0 0
      src/types/api/layot.d.ts
  58. 14 0
      src/types/declaration.d.ts
  59. 2 0
      src/types/index.d.ts
  60. 13 0
      src/utils/domShow.ts
  61. 14 0
      src/utils/history.ts
  62. 50 0
      src/utils/message.ts
  63. 16 0
      src/utils/storage.ts
  64. 27 0
      tsconfig.json
  65. 10746 0
      yarn.lock

+ 12 - 0
.editorconfig

@@ -0,0 +1,12 @@
+root = true # 控制配置文件 .editorconfig 是否生效的字段
+ 
+[**] # 匹配全部文件
+indent_style = space # 缩进风格,可选space|tab
+indent_size = 2 # 缩进的空格数
+charset = utf-8 # 设置字符集
+trim_trailing_whitespace = true # 删除一行中的前后空格
+insert_final_newline = true # 设为true表示使文件以一个空白行结尾
+end_of_line = lf
+ 
+[**.md] # 匹配md文件
+trim_trailing_whitespace = false

+ 24 - 0
.gitignore

@@ -0,0 +1,24 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+staticData
+/.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*

+ 2 - 0
.npmrc

@@ -0,0 +1,2 @@
+registry=https://registry.npmmirror.com/
+@dage:registry=http://192.168.20.245:4873/

+ 11 - 0
.prettierrc.js

@@ -0,0 +1,11 @@
+module.exports = {
+  printWidth: 100, // 一行的字符数,如果超过会进行换行
+  tabWidth: 2, // 一个tab代表几个空格数,默认就是2
+  useTabs: false, // 是否启用tab取代空格符缩进,.editorconfig设置空格缩进,所以设置为false
+  semi: false, // 行尾是否使用分号,默认为true
+  singleQuote: true, // 字符串是否使用单引号
+  trailingComma: "none", // 对象或数组末尾是否添加逗号 none| es5| all
+  jsxSingleQuote: true, // 在jsx里是否使用单引号,你看着办
+  bracketSpacing: true, // 对象大括号直接是否有空格,默认为true,效果:{ foo: bar }
+  arrowParens: "avoid", // 箭头函数如果只有一个参数则省略括号
+};

+ 39 - 0
.vscode/settings.json

@@ -0,0 +1,39 @@
+{
+  "search.exclude": {
+    "/node_modules": true,
+    "dist": true,
+    "pnpm-lock.sh": true
+  },
+  "editor.formatOnSave": true,
+  "[javascript]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[javascriptreact]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[typescript]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[typescriptreact]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[json]": {
+    "editor.defaultFormatter": "vscode.json-language-features"
+  },
+  "[html]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[markdown]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[css]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[less]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[scss]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "liveServer.settings.port": 5502
+}

+ 3 - 0
README.md

@@ -0,0 +1,3 @@
+<!-- 修改了入口index=>show.html
+\node_modules\react-scripts\config\paths.js
+在public\info里面找到最新的 替换过去 -->

+ 10 - 0
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)

Diferenças do arquivo suprimidas por serem muito extensas
+ 30270 - 0
package-lock.json


+ 65 - 0
package.json

@@ -0,0 +1,65 @@
+{
+  "name": "demo",
+  "version": "0.1.0",
+  "private": true,
+  "dependencies": {
+    "@ant-design/cssinjs": "^1.5.6",
+    "@dage/krpano": "^2.2.0",
+    "@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.8.3",
+    "antd-mobile": "^5.30.0",
+    "axios": "^1.1.3",
+    "classnames": "^2.3.2",
+    "react": "^18.2.0",
+    "react-dom": "^18.2.0",
+    "react-redux": "^8.0.4",
+    "react-router-dom": "5.3",
+    "react-scripts": "5.0.1",
+    "react-sortablejs": "^6.1.4",
+    "redux": "^4.2.0",
+    "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"
+  },
+  "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/lodash": "^4.14.198",
+    "@types/react-router-dom": "^5.3.3",
+    "customize-cra": "^1.0.0",
+    "react-app-rewired": "^2.2.1"
+  },
+  "homepage": "."
+}

+ 8 - 0
path.tsconfig.json

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

BIN
public/favicon.png


+ 43 - 0
public/index.html

@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html lang="zh">
+  <head>
+    <meta charset="utf-8" />
+    <link rel="icon" href="%PUBLIC_URL%/favicon.png" />
+    <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" />
+    <script src="./info/index.js"></script>
+
+    <!--
+      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>第15届中国航展</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>

+ 71 - 0
public/info/index.js

@@ -0,0 +1,71 @@
+// 看看的数据
+const KKlist1Temp = [
+  {
+    name: '空军静展区',
+    id: 'kj',
+    children: ['空军静展区']
+  },
+  {
+    name: '海军静展区',
+    id: 'kj2',
+    children: ['海军静展区']
+  },
+  {
+    name: 'SU57',
+    id: 'kj3',
+    children: ['SU57']
+  }
+]
+
+const KKobjTemp = {
+  空军静展区: [
+    {
+      id: 'SG-kcDHg3KWc3X',
+      sceneCode: 'SG-kcDHg3KWc3X',
+      sceneTitle: '空军静展区-1',
+      type: 'kk'
+    },
+    {
+      id: 'SG-CPwbgVaPvcY',
+      sceneCode: 'SG-CPwbgVaPvcY',
+      sceneTitle: '空军静展区-2',
+      type: 'kk'
+    },
+    {
+      id: 'SG-EBnsb3F3I5g',
+      sceneCode: 'SG-EBnsb3F3I5g',
+      sceneTitle: '空军静展区-3',
+      type: 'kk'
+    },
+    {
+      id: 'SG-8GMytTLsSaJ',
+      sceneCode: 'SG-8GMytTLsSaJ',
+      sceneTitle: '空军静展区-4',
+      type: 'kk'
+    }
+  ],
+  海军静展区: [
+    {
+      id: 'SG-VZzjvTCyHV4',
+      sceneCode: 'SG-VZzjvTCyHV4',
+      sceneTitle: '海军静展区-1',
+      type: 'kk'
+    },
+    {
+      id: 'SG-K6C0Sfl4zzu',
+      sceneCode: 'SG-K6C0Sfl4zzu',
+      sceneTitle: '海军静展区-2',
+      type: 'kk'
+    }
+  ],
+  SU57: [
+    {
+      id: 'SG-2vQApDenbb8',
+      sceneCode: 'SG-2vQApDenbb8',
+      sceneTitle: 'SU57',
+      type: 'kk'
+    }
+  ]
+}
+
+const WKIDTEMP = 'WK1856238346562650112'

+ 18 - 0
public/show.html

@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="zh">
+  <head>
+    <meta charset="utf-8" />
+    <link rel="icon" href="%PUBLIC_URL%/favicon.png" />
+    <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" />
+
+    <title>第15届中国航展</title>
+  </head>
+
+  <body></body>
+  <script>
+    window.location.href = window.location.href.replace('show.html', 'index.html')
+  </script>
+</html>

+ 40 - 0
src/App.tsx

@@ -0,0 +1,40 @@
+import '@/assets/styles/base.css'
+import MessageCom from './components/Message'
+import RouterOrder from './components/RouterOrder'
+import AsyncSpinLoding from './components/AsyncSpinLoding'
+import { Image } from 'antd'
+import { useSelector } from 'react-redux'
+import store, { RootState } from './store'
+
+export default function App() {
+  // 从仓库中获取查看图片的信息
+  const lookBigImg = useSelector((state: RootState) => state.A0Layout.lookBigImg)
+  return (
+    <div id='App'>
+      {/* 关于路由 */}
+      <RouterOrder />
+      {/* 发送请求的加载组件 */}
+      <AsyncSpinLoding />
+
+      {/* 所有图片点击预览查看大图 */}
+      {lookBigImg.show ? (
+        <Image
+          preview={{
+            visible: lookBigImg.show,
+            src: lookBigImg.url,
+            onVisibleChange: value => {
+              // 清除仓库信息
+              store.dispatch({
+                type: 'layout/lookBigImg',
+                payload: { url: '', show: false }
+              })
+            }
+          }}
+        />
+      ) : null}
+
+      {/* antd 轻提示 ---兼容360浏览器 */}
+      <MessageCom />
+    </div>
+  )
+}

+ 55 - 0
src/AppM.tsx

@@ -0,0 +1,55 @@
+import '@/assets/styles/base.css'
+// 关于路由
+import { useCallback, useEffect, useRef } from 'react'
+import MessageCom from './components/Message'
+import RouterOrder from './components/RouterOrder'
+import screenImg from '@/assets/img/landtip.png'
+import AsyncSpinLoding from './components/AsyncSpinLoding'
+
+export default function AppM() {
+  const setFullFu = useCallback(() => {
+    clearTimeout(time.current)
+    time.current = window.setTimeout(() => {
+      const dom: HTMLDivElement | null = document.querySelector('#root')
+      if (dom) {
+        dom.style.height = document.documentElement.clientHeight + 'px'
+      }
+    }, 100)
+  }, [])
+
+  const time = useRef(-1)
+
+  useEffect(() => {
+    const dom: HTMLDivElement | null = document.querySelector('#root')
+    if (dom) {
+      dom.style.width = '100vw'
+      dom.style.minHeight = 'auto'
+      dom.style.height = document.documentElement.clientHeight + 'px'
+      dom.style.minWidth = 'auto'
+    }
+    window.addEventListener('resize', setFullFu, true)
+
+    return () => {
+      window.removeEventListener('resize', setFullFu)
+    }
+  }, [setFullFu])
+
+  return (
+    <div id='AppM'>
+      {/* 关于路由 */}
+      <RouterOrder />
+
+      {/* 发送请求的加载组件 */}
+      <AsyncSpinLoding />
+
+      {/* antd 轻提示 ---兼容360浏览器 */}
+      <MessageCom />
+
+      {/* 横屏提示 */}
+      <div id='ScreenChange'>
+        <img src={screenImg} alt='' />
+        <p>请在竖屏模式浏览</p>
+      </div>
+    </div>
+  )
+}

BIN
src/assets/img/IMGerror.png


BIN
src/assets/img/bg.jpg


BIN
src/assets/img/bgM.jpg


BIN
src/assets/img/bgm.mp3


BIN
src/assets/img/jiantou_w.png


BIN
src/assets/img/landtip.png


BIN
src/assets/img/loading.gif


BIN
src/assets/img/logo.png


BIN
src/assets/img/share.jpg


BIN
src/assets/img/top4.png


+ 196 - 0
src/assets/styles/base.css

@@ -0,0 +1,196 @@
+* {
+  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: black;
+}
+a {
+  text-decoration: none;
+  color: black;
+  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;
+  min-height: 100px !important;
+}
+/* 主题色 */
+:root {
+  --themeColor: #0068b7;
+  --themeColor2: #0068b7;
+}
+/* 找不到页面 */
+.noFindPage {
+  padding-top: 100px;
+  opacity: 0;
+  transition: opacity 0.5s;
+}
+#root {
+  width: 100vw;
+  height: 100vh;
+  min-width: 1600px;
+  min-height: 900px;
+  overflow: auto;
+  overflow-y: overlay;
+  /* antd图片预览组件 */
+}
+#root #App {
+  width: 100%;
+  height: 100%;
+  position: relative;
+}
+#root #App > div {
+  width: 100%;
+  height: 100%;
+}
+#root #AppM {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  max-width: 500px;
+  margin: 0 auto;
+}
+#root #AppM > div {
+  width: 100%;
+  height: 100%;
+}
+#root #AppM .noFindPage {
+  padding-top: 0;
+}
+#root .ant-image {
+  display: none;
+}
+#root .ant-carousel {
+  width: 100%;
+  height: 100%;
+}
+#root .ant-carousel .slick-slider,
+#root .ant-carousel .slick-track,
+#root .ant-carousel .slick-slide,
+#root .ant-carousel .slick-list {
+  width: 100%;
+  height: 100%;
+}
+#root .ant-carousel .slick-slide > div {
+  width: 100%;
+  height: 100%;
+}
+#root .ant-carousel .adm-image {
+  width: 100% !important;
+  height: 100% !important;
+}
+[hidden] {
+  display: none !important;
+}
+.mySorrlNo::-webkit-scrollbar {
+  /*滚动条整体样式*/
+  width: 0px;
+  /*高宽分别对应横竖滚动条的尺寸*/
+  height: 0px;
+}
+.mySorrlNo::-webkit-scrollbar-thumb {
+  /*滚动条里面小方块*/
+  border-radius: 10px;
+  -webkit-box-shadow: inset 0 0 5px transparent;
+  background: transparent;
+}
+.mySorrlNo::-webkit-scrollbar-track {
+  /*滚动条里面轨道*/
+  -webkit-box-shadow: inset 0 0 5px transparent;
+  border-radius: 10px;
+  background: transparent;
+}
+.mySorrl::-webkit-scrollbar {
+  /*滚动条整体样式*/
+  width: 5px;
+  /*高宽分别对应横竖滚动条的尺寸*/
+  height: 5px;
+}
+.mySorrl::-webkit-scrollbar-thumb {
+  /*滚动条里面小方块*/
+  border-radius: 10px;
+  -webkit-box-shadow: inset 0 0 5px transparent;
+  background: var(--themeColor2);
+}
+.mySorrl::-webkit-scrollbar-track {
+  /*滚动条里面轨道*/
+  -webkit-box-shadow: inset 0 0 5px transparent;
+  border-radius: 10px;
+  background: rgba(0, 0, 0, 0.2);
+}
+#root {
+  /*横屏*/
+}
+#root #ScreenChange {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 10000;
+  background-color: rgba(0, 0, 0, 0.8);
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  opacity: 0;
+  pointer-events: none;
+  transition: all 0.5s;
+}
+#root #ScreenChange > img {
+  width: 200px;
+}
+#root #ScreenChange > p {
+  margin-top: 20px;
+  color: #fff;
+  font-size: 18px;
+  height: 40px;
+}
+@media screen and (orientation: landscape) {
+  #root #ScreenChange {
+    opacity: 1;
+    pointer-events: auto;
+  }
+}
+.activeTxt p div {
+  animation: txtMove 8s linear infinite;
+}
+@keyframes txtMove {
+  0% {
+    left: -80px;
+  }
+  100% {
+    left: -300px;
+  }
+}
+.ant-image-preview-operations {
+  background-color: rgba(0, 0, 0, 0.6) !important;
+}
+.ant-image-preview-close {
+  display: none !important;
+}

+ 246 - 0
src/assets/styles/base.less

@@ -0,0 +1,246 @@
+* {
+  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: black;
+}
+
+a {
+  text-decoration: none;
+  color: black;
+  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;
+  min-height: 100px !important;
+}
+
+/* 主题色 */
+:root {
+  --themeColor: #0068b7;
+  --themeColor2: #0068b7;
+}
+
+/* 找不到页面 */
+.noFindPage {
+  padding-top: 100px;
+  opacity: 0;
+  transition: opacity 0.5s;
+}
+
+// 重置antd样式
+#root {
+  width: 100vw;
+  height: 100vh;
+  min-width: 1600px;
+  min-height: 900px;
+  overflow: auto;
+  overflow-y: overlay;
+
+  // pc端App组件的样式
+  #App {
+    width: 100%;
+    height: 100%;
+    position: relative;
+
+    & > div {
+      width: 100%;
+      height: 100%;
+    }
+  }
+
+  // 移动端AppM组件的样式
+  #AppM {
+    width: 100%;
+    height: 100%;
+    overflow: hidden;
+    max-width: 500px;
+    margin: 0 auto;
+
+    & > div {
+      width: 100%;
+      height: 100%;
+    }
+
+    .noFindPage {
+      padding-top: 0;
+    }
+  }
+
+  /* antd图片预览组件 */
+  .ant-image {
+    display: none;
+  }
+
+  // 走马灯样式
+  .ant-carousel {
+    width: 100%;
+    height: 100%;
+
+    .slick-slider,
+    .slick-track,
+    .slick-slide,
+    .slick-list {
+      width: 100%;
+      height: 100%;
+    }
+
+    .slick-slide > div {
+      width: 100%;
+      height: 100%;
+    }
+
+    .adm-image {
+      width: 100% !important;
+      height: 100% !important;
+    }
+  }
+}
+
+[hidden] {
+  display: none !important;
+}
+
+// 滚动条
+.mySorrlNo::-webkit-scrollbar {
+  /*滚动条整体样式*/
+  width: 0px;
+  /*高宽分别对应横竖滚动条的尺寸*/
+  height: 0px;
+}
+
+.mySorrlNo::-webkit-scrollbar-thumb {
+  /*滚动条里面小方块*/
+  border-radius: 10px;
+  -webkit-box-shadow: inset 0 0 5px transparent;
+  background: transparent;
+}
+
+.mySorrlNo::-webkit-scrollbar-track {
+  /*滚动条里面轨道*/
+  -webkit-box-shadow: inset 0 0 5px transparent;
+  border-radius: 10px;
+  background: transparent;
+}
+
+// 滚动条
+.mySorrl::-webkit-scrollbar {
+  /*滚动条整体样式*/
+  width: 5px;
+  /*高宽分别对应横竖滚动条的尺寸*/
+  height: 5px;
+}
+
+.mySorrl::-webkit-scrollbar-thumb {
+  /*滚动条里面小方块*/
+  border-radius: 10px;
+  -webkit-box-shadow: inset 0 0 5px transparent;
+  background: var(--themeColor2);
+}
+
+.mySorrl::-webkit-scrollbar-track {
+  /*滚动条里面轨道*/
+  -webkit-box-shadow: inset 0 0 5px transparent;
+  border-radius: 10px;
+  background: rgba(0, 0, 0, 0.2);
+}
+
+#root {
+  // 横屏 竖屏的切换
+  #ScreenChange {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    z-index: 10000;
+    background-color: rgba(0, 0, 0, 0.8);
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    opacity: 0;
+    pointer-events: none;
+    transition: all 0.5s;
+
+    & > img {
+      width: 200px;
+    }
+
+    & > p {
+      margin-top: 20px;
+      color: #fff;
+      font-size: 18px;
+      height: 40px;
+    }
+  }
+
+  /*横屏*/
+  @media screen and (orientation: landscape) {
+    #ScreenChange {
+      opacity: 1;
+      pointer-events: auto;
+    }
+  }
+}
+
+// 首页的动画
+.activeTxt p div {
+  animation: txtMove 8s linear infinite;
+}
+
+@keyframes txtMove {
+  0% {
+    left: -80px;
+  }
+
+  // 50% {
+  //   left: 200px;
+  // }
+
+  100% {
+    left: -300px;
+  }
+}
+
+.ant-image-preview-operations {
+  background-color: rgba(0, 0, 0, 0.6) !important;
+}
+
+.ant-image-preview-close {
+  display: none !important;
+}

+ 43 - 0
src/assets/styles/iconfont/iconfont.css

@@ -0,0 +1,43 @@
+@font-face {
+  font-family: "iconfont"; /* Project id 2820495 */
+  src: url('iconfont.woff2?t=1631880378082') format('woff2'),
+       url('iconfont.woff?t=1631880378082') format('woff'),
+       url('iconfont.ttf?t=1631880378082') format('truetype');
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-a-9gedian:before {
+  content: "\e69f";
+}
+
+.icon-sangedian:before {
+  content: "\e69e";
+}
+
+.icon-jianjie:before {
+  content: "\e69d";
+}
+
+.icon-fenxiang:before {
+  content: "\e69c";
+}
+
+.icon-yinleguan:before {
+  content: "\e69b";
+}
+
+.icon-yinlekai:before {
+  content: "\e69a";
+}
+
+.icon-more:before {
+  content: "\e698";
+}
+

Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 0
src/assets/styles/iconfont/iconfont.js


+ 58 - 0
src/assets/styles/iconfont/iconfont.json

@@ -0,0 +1,58 @@
+{
+  "id": "2820495",
+  "name": "航展",
+  "font_family": "iconfont",
+  "css_prefix_text": "icon-",
+  "description": "",
+  "glyphs": [
+    {
+      "icon_id": "24432102",
+      "name": "9个点",
+      "font_class": "a-9gedian",
+      "unicode": "e69f",
+      "unicode_decimal": 59039
+    },
+    {
+      "icon_id": "24431545",
+      "name": "三个点",
+      "font_class": "sangedian",
+      "unicode": "e69e",
+      "unicode_decimal": 59038
+    },
+    {
+      "icon_id": "24431439",
+      "name": "简介",
+      "font_class": "jianjie",
+      "unicode": "e69d",
+      "unicode_decimal": 59037
+    },
+    {
+      "icon_id": "24430046",
+      "name": "分享",
+      "font_class": "fenxiang",
+      "unicode": "e69c",
+      "unicode_decimal": 59036
+    },
+    {
+      "icon_id": "24429866",
+      "name": "音乐关",
+      "font_class": "yinleguan",
+      "unicode": "e69b",
+      "unicode_decimal": 59035
+    },
+    {
+      "icon_id": "24429858",
+      "name": "音乐开",
+      "font_class": "yinlekai",
+      "unicode": "e69a",
+      "unicode_decimal": 59034
+    },
+    {
+      "icon_id": "24429570",
+      "name": "more",
+      "font_class": "more",
+      "unicode": "e698",
+      "unicode_decimal": 59032
+    }
+  ]
+}

BIN
src/assets/styles/iconfont/iconfont.ttf


BIN
src/assets/styles/iconfont/iconfont.woff


BIN
src/assets/styles/iconfont/iconfont.woff2


+ 21 - 0
src/components/AsyncSpinLoding/index.module.scss

@@ -0,0 +1,21 @@
+.AsyncSpinLoding {
+  opacity: 0;
+  pointer-events: none;
+  transition: all .5s;
+  position: fixed;
+  z-index: 9998;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  // background-color: rgba(0, 0, 0, .6);
+  background-color: transparent;
+  :global{
+    .ant-spin-spinning{
+      position: absolute;
+      top: 50%;
+      left: 50%;
+      transform: translate(-50%,-50%);
+    }
+  }
+}

+ 15 - 0
src/components/AsyncSpinLoding/index.tsx

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

+ 16 - 0
src/components/LazyImg/index.module.scss

@@ -0,0 +1,16 @@
+.LazyImg {
+  width: 100% !important;
+  height: 100% !important;
+  :global {
+    .lodingTxt {
+      font-size: 12px;
+      width: 100%;
+      height: 100%;
+      min-height: 60px;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      color: var(--themeColor2);
+    }
+  }
+}

+ 22 - 0
src/components/LazyImg/index.tsx

@@ -0,0 +1,22 @@
+import React from 'react'
+import styles from './index.module.scss'
+import { Image } from 'antd-mobile'
+
+type Props = {
+  src: string
+}
+
+function LazyImg({ src }: Props) {
+  return (
+    <Image
+      className={styles.LazyImg}
+      lazy
+      src={src}
+      placeholder={<div className='lodingTxt'>加载中...</div>}
+    />
+  )
+}
+
+const MemoLazyImg = React.memo(LazyImg)
+
+export default MemoLazyImg

+ 27 - 0
src/components/Message/index.tsx

@@ -0,0 +1,27 @@
+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

+ 30 - 0
src/components/NotFound/index.tsx

@@ -0,0 +1,30 @@
+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 style={{ display: 'flex', justifyContent: 'center' }}>
+        <Button type='primary' onClick={() => history.replace('/')}>
+          首页
+        </Button>
+        &emsp;
+        <Button onClick={() => history.go(-1)}>返回</Button>
+      </div>
+    </div>
+  )
+}

+ 41 - 0
src/components/RouterOrder.tsx

@@ -0,0 +1,41 @@
+import history from '@/utils/history'
+import React from 'react'
+import { Route, Router, Switch } from 'react-router-dom'
+import SpinLoding from './SpinLoding'
+import NotFound from '@/components/NotFound'
+
+const routerArr = [
+  {
+    id: 1,
+    name: '首页',
+    path: '/',
+    exact: true,
+    Com: React.lazy(() => import('@/pages/A1home'))
+  },
+
+  {
+    id: 9,
+    name: '找不到页面',
+    path: '*',
+    exact: false,
+    Com: NotFound
+  }
+]
+
+function RouterOrder() {
+  return (
+    <Router history={history}>
+      <React.Suspense fallback={<SpinLoding />}>
+        <Switch>
+          {routerArr.map(v => (
+            <Route key={v.id} path={v.path} exact={v.exact} component={v.Com} />
+          ))}
+        </Switch>
+      </React.Suspense>
+    </Router>
+  )
+}
+
+const MemoRouterOrder = React.memo(RouterOrder)
+
+export default MemoRouterOrder

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

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

+ 13 - 0
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;

+ 37 - 0
src/index.tsx

@@ -0,0 +1,37 @@
+// import 'default-passive-events';
+import App from './App'
+import AppM from './AppM'
+
+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'
+
+import { isMobileFu } from './utils/history'
+
+const container = document.getElementById('root') as HTMLElement
+const root = createRoot(container)
+
+root.render(
+  <ConfigProvider
+    locale={locale}
+    theme={{
+      token: {
+        colorPrimary: '#0068b7'
+      }
+    }}
+  >
+    <Provider store={store}>
+      <StyleProvider hashPriority='high' transformers={[legacyLogicalPropertiesTransformer]}>
+        {/* 渲染 移动端 或 pc端 */}
+        {isMobileFu() ? <AppM /> : <App />}
+      </StyleProvider>
+    </Provider>
+  </ConfigProvider>
+)

+ 19 - 0
src/pages/A1home/Bottom/data.ts

@@ -0,0 +1,19 @@
+export type MyList1Type = {
+  children: string[]
+  name: string
+  id: string
+}
+
+export type MyObjRowType = {
+  sceneCode: string
+  icon: string
+  id: string
+  sceneTitle: string
+  type?: 'kk'
+}
+
+// export const myList1: MyList1Type[] = myList1Temp
+
+// export const myObj: { any: MyObjRowType[] } = myObjTemp
+
+export const WKID: string = WKIDTEMP

+ 183 - 0
src/pages/A1home/Bottom/index.module.scss

@@ -0,0 +1,183 @@
+.Bottom {
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  height: 240px;
+  z-index: 10;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  transition: all 0.5s;
+  background: linear-gradient(
+    0deg,
+    rgba(32, 32, 32, 0.8) 0,
+    rgba(32, 32, 32, 0) 90%,
+    rgba(32, 32, 32, 0)
+  );
+  :global {
+    .B1box {
+      width: 100%;
+      text-align: center;
+      .B1box_1 {
+        width: auto;
+        min-width: 960px;
+        max-width: 100%;
+        overflow-y: auto;
+        height: 112px;
+        background: linear-gradient(90deg, rgba(32, 32, 32, 0), #202020, rgba(32, 32, 32, 0));
+        white-space: nowrap;
+        display: inline-block;
+        text-align: center;
+        padding: 0 20px;
+        &::-webkit-scrollbar-thumb {
+          background: #fff;
+        }
+        & > div {
+          cursor: pointer;
+          display: inline-block;
+          position: relative;
+          width: 88px;
+          height: 88px;
+          margin: 10px 6px 0;
+          border-radius: 4px;
+          overflow: hidden;
+          border: 1px solid #fff;
+          img {
+            object-fit: cover !important;
+          }
+          p {
+            position: absolute;
+            bottom: 0;
+            left: 0;
+            width: 100%;
+            height: 100%;
+            height: 24px;
+            padding: 0 3px;
+            background: rgba(0, 0, 0, 1);
+            opacity: 0.6;
+            & > span {
+              position: relative;
+              display: inline-block;
+              width: 100%;
+              height: 100%;
+              font-size: 14px;
+              color: #fff;
+              line-height: 26px;
+              text-align: center;
+              overflow: hidden;
+              text-overflow: ellipsis;
+              white-space: nowrap;
+            }
+            & > div {
+              position: relative;
+              display: inline-block;
+              height: 100%;
+              font-size: 14px;
+              color: #fff;
+              line-height: 26px;
+              text-align: center;
+
+              width: auto;
+              display: inline-block;
+              font-weight: 700;
+              color: var(--themeColor);
+            }
+          }
+        }
+        .activeTxt {
+          border-color: var(--themeColor);
+          p {
+            opacity: 1;
+            background-color: rgba(255, 255, 255, 0.6);
+          }
+        }
+      }
+    }
+    .B1box2 {
+      margin: 10px auto;
+      border: 2px solid #0c5bf6;
+      border-radius: 30px;
+      padding: 8px 15px 0;
+      position: relative;
+      min-width: 450px;
+      max-width: 864px;
+      text-align: center;
+
+      .B1box2_1 {
+        width: auto;
+        max-width: 100%;
+        overflow-y: auto;
+        white-space: nowrap;
+        display: inline-block;
+        text-align: center;
+        padding-bottom: 6px;
+        &::-webkit-scrollbar {
+          height: 3px;
+        }
+        & > div {
+          opacity: 0.6;
+          color: #fff;
+          font-size: 16px;
+          border: 1px solid #fff;
+          border-radius: 24px;
+          padding: 6px 9px;
+          margin: 0 5px;
+          cursor: pointer;
+          display: inline-block;
+        }
+        .active {
+          opacity: 1;
+          border: 1px solid var(--themeColor);
+        }
+      }
+    }
+
+    .B3box {
+      cursor: pointer;
+      position: absolute;
+      bottom: 15px;
+      z-index: 10;
+      transition: all 0.5s;
+      & > img {
+        width: 40px;
+      }
+    }
+
+    @media screen and (max-width: 1000px) {
+      .B1box {
+        .B1box_1 {
+          min-width: 100%;
+        }
+      }
+
+      .B1box2 {
+        min-width: 100%;
+        width: 100%;
+      }
+
+      .B3box {
+        display: flex;
+        flex-direction: column;
+        justify-content: flex-end;
+        height: 50px;
+      }
+    }
+  }
+}
+
+.BottomHide {
+  bottom: -240px;
+  :global {
+    .B3box {
+      bottom: 255px;
+      transform: rotate(180deg);
+    }
+    @media screen and (max-width: 1000px) {
+      .B3box {
+        bottom: 265px !important;
+        justify-content: start;
+      }
+    }
+  }
+}

+ 172 - 0
src/pages/A1home/Bottom/index.tsx

@@ -0,0 +1,172 @@
+import React, { useCallback, useEffect, useRef, useState } from 'react'
+import styles from './index.module.scss'
+
+import xiaImg from '@/assets/img/jiantou_w.png'
+import classNames from 'classnames'
+import LazyImg from '@/components/LazyImg'
+import { MyList1Type, MyObjRowType } from './data'
+
+type Props = {
+  setTopObj: (val: MyObjRowType) => void
+  isPageShow: boolean
+}
+
+function Bottom({ setTopObj, isPageShow = false }: Props) {
+  const srollRef = useRef<HTMLDivElement>(null)
+  const srollRef2 = useRef<HTMLDivElement>(null)
+  const mousemoveFu = useCallback((ev: any, dom: HTMLDivElement | null) => {
+    if (dom) {
+      const nowMove = dom.scrollLeft
+      // 滚轮
+      let num = 200
+      if (ev.deltaY < 0) num = -num
+      dom.scrollLeft = nowMove + num
+    }
+  }, [])
+
+  // 获取数据
+  const [myObj, setMyObj] = useState({} as { any: MyObjRowType[] })
+
+  const [myList1, setMyList1] = useState([] as MyList1Type[])
+
+  useEffect(() => {
+    if (myList1[0] && myList1[0].children && myList1[0].children[0]) setAc1(myList1[0].children[0])
+  }, [myList1])
+
+  const getInfoFu = useCallback((data: any) => {
+    const myList1Temp = data.catalogRoot
+
+    const myObjTemp: any = {}
+    data.scenes.forEach((v: any) => {
+      myList1Temp.forEach((c: any) => {
+        if (c.children[0] === v.category) {
+          if (myObjTemp[c.children[0]]) myObjTemp[c.children[0]].push(v)
+          else myObjTemp[c.children[0]] = [v]
+        }
+      })
+    })
+
+    for (const key in myObjTemp) {
+      myObjTemp[key] = myObjTemp[key].sort(
+        (a: any, b: any) => Number(a.sceneTitle.split('-')[1]) - Number(b.sceneTitle.split('-')[1])
+      )
+    }
+
+    setMyList1([...KKlist1Temp, ...myList1Temp])
+    setMyObj({ ...KKobjTemp, ...myObjTemp })
+  }, [])
+
+  useEffect(() => {
+    // 待完善路径
+    fetch(`https://4dkk.4dage.com/720yun_fd_manage/${WKIDTEMP}/someData.json`)
+      .then(res => {
+        return res.json()
+      })
+      .then(data => {
+        getInfoFu(data)
+      })
+  }, [getInfoFu])
+
+  const [isShow, setIsShow] = useState(true)
+
+  // 一级别目录选中
+  const [ac1, setAc1] = useState('')
+
+  // 二级别code码
+
+  const [codeArr, setCodeArr] = useState<MyObjRowType[]>([])
+
+  const [code, setCode] = useState<{ type: 'kk' | 'qj'; mm: string }>({ type: 'kk', mm: '' })
+
+  useEffect(() => {
+    console.log('code:', code)
+  }, [code])
+
+  // 第一级目录变化的时候
+  useEffect(() => {
+    if (ac1) {
+      const arr: MyObjRowType[] = Reflect.get(myObj, ac1) || []
+      setCode({ type: 'qj', mm: arr[0].sceneCode })
+      setCodeArr(arr)
+      setTopObj(arr[0])
+      setTimeout(() => {
+        if (srollRef.current) srollRef.current.scrollLeft = 0
+      }, 500)
+    }
+    // 这里忽略
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [ac1])
+
+  // 点击二级目录
+  const setAcObj = useCallback(
+    (info: MyObjRowType) => {
+      setTopObj(info)
+      setCode({ type: 'qj', mm: info.sceneCode })
+    },
+    [setTopObj]
+  )
+
+  return (
+    <div hidden={isPageShow} className={classNames(styles.Bottom, isShow ? '' : styles.BottomHide)}>
+      <div className='B1box'>
+        <div
+          className='B1box_1 mySorrl'
+          ref={srollRef}
+          onWheel={e => mousemoveFu(e, srollRef.current)}
+        >
+          {codeArr.map(item => (
+            <div
+              onClick={() => setAcObj(item)}
+              key={item.id}
+              className={classNames(code.mm === item.sceneCode ? 'activeTxt' : '')}
+            >
+              {/* 图片路径待完善 */}
+              <LazyImg
+                src={
+                  item.type === 'kk'
+                    ? `https://4dkk.4dage.com/scene_view_data/${item.sceneCode}/user/thumb-2k.jpg`
+                    : item.icon
+                }
+              />
+              <p>
+                {code.mm === item.sceneCode ? (
+                  <div>
+                    {item.sceneTitle}&emsp;&emsp;{item.sceneTitle}&emsp;&emsp;{item.sceneTitle}
+                  </div>
+                ) : (
+                  <span>{item.sceneTitle}</span>
+                )}
+              </p>
+            </div>
+          ))}
+        </div>
+      </div>
+
+      <div className='B1box2'>
+        <div
+          className='B1box2_1 mySorrl'
+          ref={srollRef2}
+          onWheel={e => mousemoveFu(e, srollRef2.current)}
+        >
+          {myList1.map(item => (
+            <div
+              className={classNames(ac1 === item.children[0] ? 'active' : '')}
+              onClick={() => setAc1(item.children[0])}
+              key={item.children[0]}
+            >
+              {item.name}
+            </div>
+          ))}
+        </div>
+      </div>
+
+      <div className='B3box' onClick={() => setIsShow(!isShow)}>
+        <img src={xiaImg} alt='' />
+      </div>
+    </div>
+  )
+}
+
+const MemoBottom = React.memo(Bottom)
+
+export default MemoBottom

+ 67 - 0
src/pages/A1home/Share/index.module.scss

@@ -0,0 +1,67 @@
+.Share {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 9999;
+  background-color: rgba(0, 0, 0, 0.6);
+  backdrop-filter: blur(10px);
+  transition: all 0.3s;
+  :global {
+    .sharBox {
+      padding: 20px;
+      width: 30%;
+      transform: translate(-50%, -50%);
+      top: 50%;
+      left: 50%;
+      position: absolute;
+      background-color: rgba(0, 0, 0, 0.5);
+      border-radius: 10px;
+      color: #fff;
+      font-size: 16px;
+      .sharLink {
+        text-align: center;
+        padding: 30px 20px;
+        width: 80%;
+        margin: 20px auto;
+        background-color: rgba(0, 0, 0, 0.35);
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+      }
+      .sharBtn {
+        width: 100%;
+        display: flex;
+        justify-content: space-around;
+        align-items: center;
+        margin-bottom: 20px;
+        & > span {
+          text-align: center;
+          color: #fff;
+          border: 1px solid #ccc;
+          background-color: transparent;
+          border-radius: 30px;
+          width: 200px;
+          height: 40px;
+          line-height: 40px;
+          cursor: pointer;
+        }
+        .sharBtnOk {
+          background-color: #0c5bf6;
+          border: 1px solid #0c5bf6;
+        }
+      }
+    }
+    @media screen and (max-width: 1000px) {
+      .sharBox {
+        width: 100%;
+        .sharBtn {
+          & > span {
+            width: 150px;
+          }
+        }
+      }
+    }
+  }
+}

+ 51 - 0
src/pages/A1home/Share/index.tsx

@@ -0,0 +1,51 @@
+import React, { useCallback, useEffect, useState } from 'react'
+import styles from './index.module.scss'
+import { MessageFu } from '@/utils/message'
+
+type Props = {
+  isShow: boolean
+  closeFu: () => void
+}
+
+function Share({ isShow, closeFu }: Props) {
+  const [url, setUrl] = useState('')
+  useEffect(() => {
+    setUrl(window.location.href.replace('index.html', 'show.html').replace('#/', ''))
+  }, [])
+
+  const btnOk = useCallback(() => {
+    const input = document.createElement('input')
+    const body = document.body
+    body.appendChild(input)
+    input.value = url
+    input.select()
+    document.execCommand('copy')
+    body.removeChild(input)
+
+    MessageFu.success('复制成功')
+    closeFu()
+  }, [closeFu, url])
+
+  return (
+    <div
+      className={styles.Share}
+      style={{ opacity: isShow ? '1' : '0', pointerEvents: isShow ? 'auto' : 'none' }}
+    >
+      <div className='sharBox'>
+        <p>分享链接给好友</p>
+        <div className='sharLink'>{url}</div>
+
+        <div className='sharBtn'>
+          <span onClick={closeFu}>取消</span>
+          <span className='sharBtnOk' onClick={btnOk}>
+            一键复制
+          </span>
+        </div>
+      </div>
+    </div>
+  )
+}
+
+const MemoShare = React.memo(Share)
+
+export default MemoShare

+ 171 - 0
src/pages/A1home/index.module.scss

@@ -0,0 +1,171 @@
+.A1home {
+  background-color: #7dbded;
+  position: relative;
+  overflow: hidden;
+  :global {
+    .box1 {
+      width: 100%;
+      height: 100%;
+      background-repeat: no-repeat;
+      background-image: url('../../assets/img/bg.jpg');
+      position: relative;
+      z-index: 9999;
+      .b1logo {
+        position: absolute;
+        left: 40px;
+        top: 30px;
+        width: 140px;
+        pointer-events: none;
+      }
+
+      .b1Btn {
+        position: absolute;
+        bottom: 10%;
+        left: 50%;
+        transform: translateX(-50%);
+        text-align: center;
+        width: 100%;
+        .b1img {
+          pointer-events: none;
+          max-width: 100%;
+          display: block;
+          margin: 0 auto;
+        }
+
+        & > ul {
+          margin: 110px auto 0;
+          width: 365px;
+          & > li {
+            border: 2px solid var(--themeColor);
+            height: 60px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            border-radius: 40px;
+            letter-spacing: 2px;
+            cursor: pointer;
+            color: var(--themeColor);
+            background-color: rgba(255, 255, 255, 0.4);
+            font-size: 20px;
+            &:last-of-type {
+              margin-top: 30px;
+            }
+          }
+        }
+      }
+    }
+
+    // 右侧按钮
+    .v_aside {
+      font-size: 16px;
+      top: 50%;
+      position: absolute;
+      right: 20px;
+      color: #fff;
+      text-shadow: 0px 0px 4px rgba(0, 0, 0, 0.4);
+      z-index: 2004;
+      & > ul {
+        transform: translateY(-50%);
+        & > li {
+          cursor: pointer;
+          background: rgba(0, 0, 0, 0.4);
+          border-radius: 50%;
+          padding: 2px 8px;
+          cursor: pointer;
+          margin: 10px 0;
+          & > i {
+            font-size: 28px;
+            cursor: pointer;
+          }
+        }
+      }
+    }
+
+    // 顶部标题
+    .A1title {
+      pointer-events: none;
+      position: absolute;
+      z-index: 99;
+      margin: 0;
+      height: 40px;
+      line-height: 40px;
+      font-size: 18px;
+      font-weight: 700;
+      color: #fff;
+      padding: 0 15px;
+      display: inline-block;
+      text-shadow: 1px 0 2px rgb(0 0 0);
+      left: 50%;
+      transform: translateX(-50%) translateY(0);
+      width: 40%;
+      top: 20px;
+      background: linear-gradient(
+        90deg,
+        transparent,
+        rgba(0, 0, 0, 0.2) 29%,
+        rgba(0, 0, 0, 0.2) 69%,
+        transparent
+      );
+      margin-top: 0;
+      text-align: center;
+    }
+    .iframeBox {
+      position: absolute;
+      top: 0;
+      left: 0;
+      width: 100%;
+      height: 100%;
+      background-color: #232323;
+      iframe {
+        width: 100%;
+        height: 100%;
+      }
+    }
+
+    @media screen and (max-width: 1000px) {
+      .box1 {
+        background-image: url('../../assets/img/bgM.jpg');
+        background-size: 100% 100%;
+        .b1logo {
+          right: 0;
+          top: 0;
+          left: auto;
+          width: 30%;
+        }
+        .b1Btn {
+          bottom: 5%;
+
+          & > ul {
+            margin: 38% auto 0;
+            width: 50%;
+            & > li {
+              margin-bottom: 14px;
+            }
+          }
+        }
+      }
+
+      // 右侧按钮
+      .v_aside {
+        font-size: 14px;
+        top: 10px;
+        right: 10px;
+        & > ul {
+          transform: translateY(0);
+          & > li {
+            cursor: pointer;
+            background: rgba(0, 0, 0, 0.4);
+            border-radius: 50%;
+            padding: 2px 8px;
+            cursor: pointer;
+            margin: 10px 0;
+            & > i {
+              font-size: 20px;
+              cursor: pointer;
+            }
+          }
+        }
+      }
+    }
+  }
+}

+ 116 - 0
src/pages/A1home/index.tsx

@@ -0,0 +1,116 @@
+import React, { useCallback, useEffect, useRef, useState } from 'react'
+import styles from './index.module.scss'
+
+import classNames from 'classnames'
+import { isMobileFu } from '@/utils/history'
+
+import '@/assets/styles/iconfont/iconfont.css'
+
+import logoImg from '@/assets/img/logo.png'
+import top4Img from '@/assets/img/top4.png'
+import bgmMp3 from '@/assets/img/bgm.mp3'
+import Share from './Share'
+import Bottom from './Bottom'
+import { MyObjRowType, WKID } from './Bottom/data'
+
+function A1home() {
+  const audioRef = useRef<HTMLAudioElement>(null)
+
+  const clickBtn = useCallback(() => {
+    setBaseShow(false)
+    setAudioSta(true)
+  }, [])
+
+  // 首页的显示和隐藏
+  const [baseShow, setBaseShow] = useState(true)
+
+  useEffect(() => {
+    if (window.location.href.includes('?type=kj')) {
+      setBaseShow(false)
+    }
+  }, [])
+
+  // 音乐的播放和暂停
+  const [audioSta, setAudioSta] = useState(false)
+  useEffect(() => {
+    if (audioRef.current) audioSta ? audioRef.current.play() : audioRef.current.pause()
+  }, [audioSta])
+
+  // 分享页面
+  const [share, setShare] = useState(false)
+
+  // 选中的对象数据
+
+  const [acObj, setAcObj] = useState({} as MyObjRowType)
+
+  useEffect(() => {
+    console.log('acObj:', acObj)
+  }, [acObj])
+
+  return (
+    <div className={styles.A1home}>
+      <audio ref={audioRef} src={bgmMp3} loop />
+      {/* 初始页面 */}
+      <div className='box1' hidden={!baseShow}>
+        <img className='b1logo' src={logoImg} alt='' />
+
+        <div className='b1Btn'>
+          <img className='b1img' src={top4Img} alt='' />
+          <ul>
+            {/* 待完善 */}
+            <li style={{ opacity: 0, pointerEvents: 'none' }}>展馆漫游</li>
+            <li onClick={clickBtn}>展区漫游</li>
+          </ul>
+        </div>
+      </div>
+      {/* 右侧按钮 */}
+      <div className='v_aside'>
+        <ul>
+          {/* 待完善 */}
+          <li hidden>
+            <i className='iconfont icon-jianjie'></i>
+          </li>
+          <li onClick={() => setAudioSta(!audioSta)}>
+            <i
+              className={classNames('iconfont', audioSta ? 'icon-yinlekai' : 'icon-yinleguan')}
+            ></i>
+          </li>
+          <li onClick={() => setShare(true)}>
+            <i className='iconfont icon-fenxiang'></i>
+          </li>
+        </ul>
+      </div>
+      {/* 分享页面 */}
+      <Share isShow={share} closeFu={() => setShare(false)} />
+      {/* 底部页面 */}
+      <Bottom setTopObj={val => setAcObj(val)} isPageShow={baseShow} />
+      {/* 顶部title */}
+      {acObj.sceneCode ? (
+        <>
+          {/* <div className='A1title'>{acObj.sceneTitle}</div> */}
+
+          <div className='iframeBox'>
+            {/* 地址待完善 */}
+            <iframe
+              key={acObj.sceneCode}
+              src={
+                acObj.type === 'kk'
+                  ? `https://www.4dkankan.com/spg.html?m=${acObj.sceneCode}&hideNav`
+                  : `https://www.4dkankan.com/panorama/${
+                      isMobileFu() ? 'airShowMobile' : 'airShow'
+                    }.html?id=${WKID}&vr=${acObj.sceneCode}`
+              }
+              frameBorder='0'
+              title='qj'
+            ></iframe>
+          </div>
+        </>
+      ) : null}
+      {/* 嵌套页面 */}
+    </div>
+  )
+}
+
+const MemoA1home = React.memo(A1home)
+
+export default MemoA1home

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

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

+ 14 - 0
src/pages/初始化组件 copy/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
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

+ 14 - 0
src/store/reducer/index.ts

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

+ 36 - 0
src/store/reducer/layout.ts

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

+ 0 - 0
src/types/api/layot.d.ts


+ 14 - 0
src/types/declaration.d.ts

@@ -0,0 +1,14 @@
+declare module 'history'
+declare module '*.scss'
+declare module '*.png'
+declare module '*.jpg'
+declare module '*.mp3'
+declare module '*.gif'
+declare module '*.svg'
+declare module 'js-export-excel'
+declare module 'braft-utils'
+
+// public/myData.js 里面的一些数据的类型
+declare const KKlist1Temp
+declare const KKobjTemp
+declare const WKIDTEMP

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

@@ -0,0 +1,2 @@
+export * from './api/layot'
+

+ 13 - 0
src/utils/domShow.ts

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

+ 14 - 0
src/utils/history.ts

@@ -0,0 +1,14 @@
+import { createHashHistory } from 'history'
+const history = createHashHistory()
+export default history
+
+// 判断是手机端还是pc端
+export const isMobileFu = () => {
+  if (
+    window.navigator.userAgent.match(
+      /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i
+    )
+  ) {
+    return true
+  } else return false
+}

+ 50 - 0
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,
+      },
+    });
+  },
+};

+ 16 - 0
src/utils/storage.ts

@@ -0,0 +1,16 @@
+// 本地存储-临时会话
+const TOKEN_KEY = "KP_WEB_TIT";
+
+/**
+ * 获取临时存储信息
+ */
+export const getTitFu = (): string[] => {
+  return JSON.parse(sessionStorage.getItem(TOKEN_KEY) || "[]");
+};
+
+/**
+ *  信息存入缓存
+ */
+export const setTitFu = (val: string[]): void => {
+  sessionStorage.setItem(TOKEN_KEY, JSON.stringify(val));
+};

+ 27 - 0
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"
+  ]
+}

Diferenças do arquivo suprimidas por serem muito extensas
+ 10746 - 0
yarn.lock