Explorar el Código

Merge branch 'master' of http://face3d.4dage.com:7005/chenzimin2/ZGZQBWG

任一存 hace 2 años
padre
commit
a3a3655370
Se han modificado 96 ficheros con 30783 adiciones y 605 borrados
  1. 3 0
      hot/.browserslistrc
  2. 17 0
      hot/.eslintrc.js
  3. 23 0
      hot/.gitignore
  4. 24 0
      hot/README.md
  5. 5 0
      hot/babel.config.js
  6. 26499 0
      hot/package-lock.json
  7. 32 0
      hot/package.json
  8. 16 0
      hot/public/index.html
  9. 22 0
      hot/src/App.vue
  10. 34 0
      hot/src/assets/base.css
  11. BIN
      hot/src/assets/images/IMGerror.png
  12. BIN
      hot/src/assets/images/loading.gif
  13. BIN
      hot/src/assets/images/pc/audio.png
  14. BIN
      hot/src/assets/images/pc/audioAc.png
  15. BIN
      hot/src/assets/images/pc/icon-left.png
  16. BIN
      hot/src/assets/images/pc/icon-right.png
  17. BIN
      hot/src/assets/images/pc/icon1.png
  18. BIN
      hot/src/assets/images/pc/icon1Ac.png
  19. BIN
      hot/src/assets/images/pc/icon2.png
  20. BIN
      hot/src/assets/images/pc/icon2Ac.png
  21. BIN
      hot/src/assets/images/pc/icon3.png
  22. BIN
      hot/src/assets/images/pc/icon3Ac.png
  23. BIN
      hot/src/assets/images/pc/left.png
  24. BIN
      hot/src/assets/images/pc/right.png
  25. BIN
      hot/src/assets/logo.png
  26. 59 0
      hot/src/components/HelloWorld.vue
  27. 23 0
      hot/src/main.js
  28. 27 0
      hot/src/router/index.js
  29. 29 0
      hot/src/utils/browser.js
  30. 0 0
      hot/src/utils/http.js
  31. 5 0
      hot/src/views/About.vue
  32. 563 0
      hot/src/views/Home.vue
  33. 3 0
      hot/vue.config.js
  34. 384 6
      houtai/package-lock.json
  35. 2 0
      houtai/package.json
  36. 53 0
      houtai/src/components/Z_RichText/index.module.scss
  37. 194 0
      houtai/src/components/Z_RichText/index.tsx
  38. 19 0
      houtai/src/pages/A1Rule/RuleEdit/index.module.scss
  39. 237 0
      houtai/src/pages/A1Rule/RuleEdit/index.tsx
  40. 63 0
      houtai/src/pages/A1Rule/TopicSetting/index.module.scss
  41. 115 0
      houtai/src/pages/A1Rule/TopicSetting/index.tsx
  42. 87 3
      houtai/src/pages/A1Rule/index.module.scss
  43. 283 10
      houtai/src/pages/A1Rule/index.tsx
  44. 25 28
      houtai/src/pages/A2Integral/index.module.scss
  45. 152 380
      houtai/src/pages/A2Integral/index.tsx
  46. 53 3
      houtai/src/pages/A4Prize/index.module.scss
  47. 380 8
      houtai/src/pages/A4Prize/index.tsx
  48. 32 3
      houtai/src/pages/A5Exchange/index.module.scss
  49. 164 8
      houtai/src/pages/A5Exchange/index.tsx
  50. 34 0
      houtai/src/pages/A6IDUser/IntegralEdit/index.module.scss
  51. 221 0
      houtai/src/pages/A6IDUser/IntegralEdit/index.tsx
  52. 32 3
      houtai/src/pages/A6IDUser/index.module.scss
  53. 207 9
      houtai/src/pages/A6IDUser/index.tsx
  54. 1 1
      houtai/src/pages/C7Log/index.module.scss
  55. 8 0
      houtai/src/pages/Layout/index.tsx
  56. 5 0
      houtai/src/pages/TopicSetting/index.module.scss
  57. 14 0
      houtai/src/pages/TopicSetting/index.tsx
  58. 35 7
      houtai/src/store/action/A1Rule.ts
  59. 30 5
      houtai/src/store/action/A4Prise.ts
  60. 33 0
      houtai/src/store/action/A6IDUser.ts
  61. 49 0
      houtai/src/store/action/TopicSetting.ts
  62. 7 6
      houtai/src/store/reducer/A1Rule.ts
  63. 3 3
      houtai/src/store/reducer/A2Integral.ts
  64. 5 5
      houtai/src/store/reducer/A4Prise.ts
  65. 27 0
      houtai/src/store/reducer/A6IDUser.ts
  66. 31 0
      houtai/src/store/reducer/TopicSetting.ts
  67. 8 1
      houtai/src/store/reducer/index.ts
  68. 57 0
      houtai/src/types/api/A1Rule.ts
  69. 3 1
      houtai/src/types/api/A2Share.d.ts
  70. 29 0
      houtai/src/types/api/A4Prize.ts
  71. 38 0
      houtai/src/types/api/A6IDUser.ts
  72. 38 0
      houtai/src/types/api/TopicSetting.ts
  73. 1 0
      houtai/src/types/declaration.d.ts
  74. 5 1
      houtai/src/types/index.d.ts
  75. 43 19
      zhengquan/public/staticData/data.js
  76. BIN
      zhengquan/public/staticData/icon/xuting.png
  77. BIN
      zhengquan/public/staticData/thumbnail/img-1.png
  78. BIN
      zhengquan/public/staticData/thumbnail/img-gonyi.png
  79. BIN
      zhengquan/public/staticData/thumbnail/img-weiting.png
  80. BIN
      zhengquan/public/staticData/thumbnail/img-xuting.png
  81. 4 0
      zhengquan/src/App.vue
  82. BIN
      zhengquan/src/assets/images/home/bg1-1open.png
  83. BIN
      zhengquan/src/assets/images/home/bg1open.png
  84. BIN
      zhengquan/src/assets/images/home/bg3.png
  85. BIN
      zhengquan/src/assets/images/home/bg3open.png
  86. BIN
      zhengquan/src/assets/images/home/icon-down.png
  87. BIN
      zhengquan/src/assets/images/home/icon-up-mo.png
  88. 7 0
      zhengquan/src/images.d.ts
  89. 1 0
      zhengquan/src/utils/browser.ts
  90. 2 2
      zhengquan/src/utils/https.ts
  91. 0 28
      zhengquan/src/utils/loadScript.ts
  92. 163 52
      zhengquan/src/views/Home/components/homeTabbar.vue
  93. 10 9
      zhengquan/src/views/Home/components/sceneListInfo.vue
  94. 1 1
      zhengquan/src/views/Home/components/unitList.vue
  95. 4 2
      zhengquan/src/views/Scene/ScenePage.vue
  96. 0 1
      zhengquan/tsconfig.json

+ 3 - 0
hot/.browserslistrc

@@ -0,0 +1,3 @@
+> 1%
+last 2 versions
+not dead

+ 17 - 0
hot/.eslintrc.js

@@ -0,0 +1,17 @@
+module.exports = {
+  root: true,
+  env: {
+    node: true
+  },
+  'extends': [
+    'plugin:vue/essential',
+    'eslint:recommended'
+  ],
+  parserOptions: {
+    parser: 'babel-eslint'
+  },
+  rules: {
+    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
+    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
+  }
+}

+ 23 - 0
hot/.gitignore

@@ -0,0 +1,23 @@
+.DS_Store
+node_modules
+/dist
+
+
+# local env files
+.env.local
+.env.*.local
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 24 - 0
hot/README.md

@@ -0,0 +1,24 @@
+# hotspot
+
+## Project setup
+```
+npm install
+```
+
+### Compiles and hot-reloads for development
+```
+npm run serve
+```
+
+### Compiles and minifies for production
+```
+npm run build
+```
+
+### Lints and fixes files
+```
+npm run lint
+```
+
+### Customize configuration
+See [Configuration Reference](https://cli.vuejs.org/config/).

+ 5 - 0
hot/babel.config.js

@@ -0,0 +1,5 @@
+module.exports = {
+  presets: [
+    '@vue/cli-plugin-babel/preset'
+  ]
+}

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 26499 - 0
hot/package-lock.json


+ 32 - 0
hot/package.json

@@ -0,0 +1,32 @@
+{
+  "name": "hotspot",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "serve": "vue-cli-service serve",
+    "build": "vue-cli-service build",
+    "lint": "vue-cli-service lint"
+  },
+  "dependencies": {
+    "axios": "^0.20.0",
+    "core-js": "^3.6.5",
+    "swiper": "^5.4.5",
+    "v-viewer": "^1.5.1",
+    "vue": "^2.6.11",
+    "vue-awesome-swiper": "^4.1.1",
+    "vue-lazyload": "^1.3.3",
+    "vue-router": "^3.2.0"
+  },
+  "devDependencies": {
+    "@vue/cli-plugin-babel": "~4.5.0",
+    "@vue/cli-plugin-eslint": "~4.5.0",
+    "@vue/cli-plugin-router": "~4.5.0",
+    "@vue/cli-service": "~4.5.0",
+    "babel-eslint": "^10.1.0",
+    "eslint": "^6.7.2",
+    "eslint-plugin-vue": "^6.2.2",
+    "less": "^3.0.4",
+    "less-loader": "^5.0.0",
+    "vue-template-compiler": "^2.6.11"
+  }
+}

+ 16 - 0
hot/public/index.html

@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width,initial-scale=1.0">
+    <title><%= htmlWebpackPlugin.options.title %></title>
+  </head>
+  <body>
+    <noscript>
+      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
+    </noscript>
+    <div id="app"></div>
+    <!-- built files will be auto injected -->
+  </body>
+</html>

+ 22 - 0
hot/src/App.vue

@@ -0,0 +1,22 @@
+<template>
+  <div id="app">
+    <router-view/>
+  </div>
+</template>
+
+<style lang="less">
+html,body{
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+}
+*{
+  margin: 0;
+  padding: 0;
+}
+#app {
+  width: 100%;
+  height: 100%;
+}
+
+</style>

+ 34 - 0
hot/src/assets/base.css

@@ -0,0 +1,34 @@
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+}
+body{
+  user-select: none;
+}
+.viewer-title {
+  display: none !important;
+}
+
+.viewer-prev {
+  display: none !important;
+}
+
+.viewer-next {
+  display: none !important;
+}
+
+.viewer-navbar {
+  display: none !important;
+}
+
+.viewer-close {
+  display: none !important;
+}
+
+@media screen and (max-width: 800px) {
+  .viewer-footer {
+    bottom: auto;
+    top: 10px;
+  }
+}

BIN
hot/src/assets/images/IMGerror.png


BIN
hot/src/assets/images/loading.gif


BIN
hot/src/assets/images/pc/audio.png


BIN
hot/src/assets/images/pc/audioAc.png


BIN
hot/src/assets/images/pc/icon-left.png


BIN
hot/src/assets/images/pc/icon-right.png


BIN
hot/src/assets/images/pc/icon1.png


BIN
hot/src/assets/images/pc/icon1Ac.png


BIN
hot/src/assets/images/pc/icon2.png


BIN
hot/src/assets/images/pc/icon2Ac.png


BIN
hot/src/assets/images/pc/icon3.png


BIN
hot/src/assets/images/pc/icon3Ac.png


BIN
hot/src/assets/images/pc/left.png


BIN
hot/src/assets/images/pc/right.png


BIN
hot/src/assets/logo.png


+ 59 - 0
hot/src/components/HelloWorld.vue

@@ -0,0 +1,59 @@
+<template>
+  <div class="hello">
+    <h1>{{ msg }}</h1>
+    <p>
+      For a guide and recipes on how to configure / customize this project,<br>
+      check out the
+      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
+    </p>
+    <h3>Installed CLI Plugins</h3>
+    <ul>
+      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
+      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li>
+      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
+    </ul>
+    <h3>Essential Links</h3>
+    <ul>
+      <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
+      <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
+      <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
+      <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
+      <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
+    </ul>
+    <h3>Ecosystem</h3>
+    <ul>
+      <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
+      <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
+      <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
+      <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
+      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
+    </ul>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'HelloWorld',
+  props: {
+    msg: String
+  }
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped lang="less">
+h3 {
+  margin: 40px 0 0;
+}
+ul {
+  list-style-type: none;
+  padding: 0;
+}
+li {
+  display: inline-block;
+  margin: 0 10px;
+}
+a {
+  color: #42b983;
+}
+</style>

+ 23 - 0
hot/src/main.js

@@ -0,0 +1,23 @@
+import Vue from 'vue'
+import App from './App.vue'
+import router from './router'
+import axios from 'axios'
+import 'viewerjs/dist/viewer.css'
+import Viewer from 'v-viewer'
+// 图片懒加载
+import VueLazyLoad from 'vue-lazyload'
+Vue.use(VueLazyLoad, {
+  error: require('@/assets/images/IMGerror.png'),
+  loading: require('@/assets/images/loading.gif')
+})
+
+Vue.config.productionTip = false
+Vue.prototype.$http = axios
+
+Vue.use(Viewer)
+
+import './assets/base.css'
+new Vue({
+  router,
+  render: h => h(App)
+}).$mount('#app')

+ 27 - 0
hot/src/router/index.js

@@ -0,0 +1,27 @@
+import Vue from 'vue'
+import VueRouter from 'vue-router'
+import Home from '../views/Home.vue'
+
+Vue.use(VueRouter)
+
+const routes = [
+  {
+    path: '/',
+    name: 'Home',
+    component: Home
+  },
+  {
+    path: '/about',
+    name: 'About',
+    // route level code-splitting
+    // this generates a separate chunk (about.[hash].js) for this route
+    // which is lazy-loaded when the route is visited.
+    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
+  }
+]
+
+const router = new VueRouter({
+  routes
+})
+
+export default router

+ 29 - 0
hot/src/utils/browser.js

@@ -0,0 +1,29 @@
+function versions () {
+    var u = window.navigator.userAgent
+    return {
+      // IE内核
+      trident: u.indexOf('Trident') > -1,
+      // opera内核
+      presto: u.indexOf('Presto') > -1,
+      // 苹果、谷歌内核
+      webKit: u.indexOf('AppleWebKit') > -1,
+      // 火狐内核
+      gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') === -1,
+      // 是否为移动终端 / Tablets use desktop version
+      mobile: (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) && !(/Tablet|iPad/i.test(navigator.userAgent)),
+      // ios终端
+      ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/),
+      // android终端或者uc浏览器
+      android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1,
+      // 是否为iPhone或者安卓QQ浏览器
+      iPhone: u.indexOf('iPhone') > -1 || u.indexOf('Mac') > -1,
+      // 是否为iPad
+      iPad: u.indexOf('iPad') > -1,
+      // 是否为web应用程序,没有头部与底部
+      webApp: u.indexOf('Safari') === -1,
+      // 是否为微信浏览器
+      weixin: ~u.indexOf('MicroMessenger')
+    }
+  }
+  
+  export default versions()

+ 0 - 0
hot/src/utils/http.js


+ 5 - 0
hot/src/views/About.vue

@@ -0,0 +1,5 @@
+<template>
+  <div class="about">
+    <h1>This is an about page</h1>
+  </div>
+</template>

+ 563 - 0
hot/src/views/Home.vue

@@ -0,0 +1,563 @@
+<template>
+  <div class="home">
+    <div class="main">
+      <div class="mainCon" v-show="!oneTxt">
+        <!-- 音频播放器 -->
+        <audio id="myAudio" v-if="audio" v-show="isOneAduio" :src="audio" controls></audio>
+        <!-- 音频图标 -->
+        <div class="audioIcon" v-if="audio && !isOneAduio" @click="audioSta = !audioSta"
+          :title="audioSta ? '关闭音频' : '打开音频'">
+          <img :src="require(`@/assets/images/pc/audio${audioSta ? 'Ac' : ''}.png`)
+            " alt="" />
+        </div>
+
+        <!-- 如果只有一个模块 -->
+        <div class="oneTabNum" v-if="flooTab.length === 1 && data[myType] && data[myType].length">
+          {{ myInd + 1 }} / {{ data[myType].length }}
+        </div>
+
+        <!-- 底部的tab -->
+        <div class="flooTabBox" v-if="flooTab.length > 1">
+          <div @click="myType = item.type" class="tabRow" :class="{ tabRowAc: myType === item.type }"
+            v-for="item in flooTab" :key="item.id">
+            <img :src="require(`@/assets/images/pc/icon${item.id}${myType === item.type ? 'Ac' : ''
+              }.png`)
+              " alt="" />
+            {{ item.name }}
+            <span v-if="data[item.type] &&
+              data[item.type].length &&
+              data[item.type].length > 1
+              ">{{ item.type === myType ? myInd + 1 + "/" : null
+  }}{{ data[item.type].length }}</span>
+          </div>
+        </div>
+
+        <!-- 主要内容 -->
+
+        <div class="contenBoxMain">
+          <div class="contenBox" :class="{ contenBoxAc: index === myInd }" v-for="(item, index) in data[myType]"
+            :key="myType === 'video' ? item.url : item">
+            <!-- 模型页面 -->
+            <div class="modelBox" v-if="myType === 'model'">
+              <iframe :src="item" frameborder="0" v-if="index === myInd"></iframe>
+            </div>
+            <!-- 视频页面 -->
+            <div class="videoBox" v-else-if="myType === 'video'">
+              <video controls :src="item.url" v-if="index === myInd"></video>
+            </div>
+            <!-- 图片页面 -->
+            <div class="imgBox" v-else-if="myType === 'img'">
+              <div class="smImgBox" @click="lookImg(item)">
+                <img v-lazy="item" alt="" />
+              </div>
+            </div>
+          </div>
+          <!-- 左右箭头 -->
+          <div @click="cutMyInd(-1, myInd === 0)" class="leftJJ awccJJ" :class="{ noClick: myInd === 0 }"
+            v-if="data[myType] && data[myType].length > 1"></div>
+          <div @click="cutMyInd(1, myInd === data[myType].length - 1)" class="rightJJ awccJJ"
+            :class="{ noClick: myInd === data[myType].length - 1 }" v-if="data[myType] && data[myType].length > 1"></div>
+        </div>
+      </div>
+
+      <!-- 下面的文字介绍 -->
+      <div class="flooTxt" :class="{ flooTxtOne: oneTxt }">
+        <div class="flooTxtBox">
+          <div class="myTitle">{{ myTitle }}</div>
+          <!-- 视频的介绍 -->
+          <div class="myTxt" v-if="myType === 'video' && videoTxt[myInd]">
+            {{ videoTxt[myInd] }}
+          </div>
+          <div class="myTxt" v-if="myType === 'img' && imgTxt[myInd]">
+            {{ imgTxt[myInd] }}
+          </div>
+          <div class="myTxt" v-html="myTxt"></div>
+        </div>
+      </div>
+    </div>
+    <!-- 查看图片 -->
+    <viewer class="viewerCla" ref="viewer" :images="lookPics">
+      <img :src="lookPics[0]" alt="" />
+    </viewer>
+  </div>
+</template>
+
+
+<script>
+export default {
+  name: "Home",
+  data() {
+    return {
+      m: this.$route.query.m,
+      id: this.$route.query.id,
+      // 音频地址
+      audio: "",
+      // 如果只有单独的音频
+      isOneAduio: false,
+      // 音频状态
+      audioSta: false,
+
+      data: {
+        // 模型数组
+        model: [],
+        // 视频数组
+        video: [],
+        // 图片数组
+        img: [],
+      },
+      // 当前 type
+      myType: "",
+
+      // 底部的tab
+      flooTab: [],
+
+      // 当前索引
+      myInd: 0,
+
+      // 查看图片
+      lookPics: [],
+
+      // 标题
+      myTitle: "",
+      // 内容
+      myTxt: "",
+      // 视频内容
+      videoTxt: [],
+      imgTxt: [],
+
+      // 只有标题和文字(没有视频,没有模型,没有图片)
+      oneTxt: false,
+    };
+  },
+  watch: {
+    myType() {
+      this.myInd = 0;
+    },
+    // 音频的开启和关闭
+    audioSta(val) {
+      const dom = document.querySelector("#myAudio");
+      if (val) {
+        dom.play();
+        dom.onended = () => {
+          // console.log("----音频播放完毕");
+          this.audioSta = false;
+        };
+      } else dom.pause();
+    },
+  },
+  computed: {},
+  components: {},
+  methods: {
+    // 点击左右箭头
+    cutMyInd(num, flag) {
+      if (flag) return;
+      this.myInd += num;
+    },
+    // 点击查看大图
+    lookImg(url) {
+      let dom = this.$refs.viewer.$viewer;
+      this.lookPics = [url];
+      dom.show();
+    },
+    async getData() {
+      // https://www.4dmodel.com/
+      let url = `https://super.4dage.com/data/${this.id
+        }/hot/js/data.js?time=${Math.random()}`;
+      let result = (await this.$http.get(url)).data;
+      const resData = result[this.m];
+      console.log("----", resData);
+      if (resData) {
+        this.audio = resData.backgroundMusic;
+        // 只有单独的音频上传
+        if (
+          resData.backgroundMusic &&
+          !resData.model &&
+          !resData.video &&
+          !resData.images
+        ) {
+          this.isOneAduio = true;
+        }
+        // 底部的tab
+        const arr = [];
+        const obj = {};
+        if (resData.model) {
+          obj.model = resData.model;
+          arr.push({ id: 1, type: "model", name: "模型" });
+        }
+        if (resData.video) {
+          obj.video = resData.video;
+          arr.push({ id: 2, type: "video", name: "视频" });
+        }
+        if (resData.images) {
+          obj.img = resData.images;
+          arr.push({ id: 3, type: "img", name: "图片" });
+        }
+        this.flooTab = arr;
+        this.data = obj;
+
+        // 当前type的值 应该为
+        if (resData.model) this.myType = "model";
+        else if (resData.video) this.myType = "video";
+        else if (resData.images) this.myType = "img";
+
+        this.myTitle = resData.title || "";
+        this.myTxt = resData.content || "";
+        this.videoTxt = resData.videosDesc || [];
+        this.imgTxt = resData.imagesDesc || [];
+
+        // 只有 标题和 文字介绍(没有视频,没有模型,没有图片)
+        if (!obj.model && !obj.video && !obj.img && !resData.backgroundMusic) {
+          this.oneTxt = true;
+        }
+      }
+    },
+  },
+  mounted() {
+    this.getData();
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.home {
+  .viewerCla img {
+    display: none;
+  }
+
+  width: 100%;
+  height: 100%;
+  background-color: rgba(0, 0, 0, 0.79);
+  // backdrop-filter: blur(10px);
+  position: relative;
+
+  #myAudio {
+    z-index: 11;
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    width: 500px;
+    height: 60px;
+  }
+
+  .main {
+    width: 1200px;
+    margin: 0 auto;
+    height: 100%;
+    padding-top: 40px;
+
+    .mainCon {
+      position: relative;
+      border-radius: 6px;
+      overflow: hidden;
+      width: 100%;
+      height: calc(100% - 200px);
+      // background: linear-gradient(#929292, #c5c5c5);
+
+      .audioIcon {
+        z-index: 10;
+        cursor: pointer;
+        position: absolute;
+        right: 20px;
+        bottom: 30px;
+      }
+
+      .oneTabNum {
+        z-index: 10;
+        position: absolute;
+        bottom: 30px;
+        left: 50%;
+        transform: translateX(-50%);
+        font-size: 14px;
+      }
+
+      .flooTabBox {
+        z-index: 10;
+        position: absolute;
+        bottom: 30px;
+        left: 50%;
+        transform: translateX(-50%);
+        display: flex;
+
+        .tabRow {
+          cursor: pointer;
+          display: flex;
+          align-items: center;
+          margin: 0 12px;
+          font-size: 12px;
+          background-color: #489182;
+          color: #FCE9AC;
+          padding: 0px 14px;
+          height: 36px;
+          border-radius: 18px;
+
+          &>img {
+            margin-right: 6px;
+          }
+        }
+
+        .tabRowAc {
+          background-color: #EAD5A3;
+          pointer-events: none;
+          color: #489182;
+        }
+      }
+
+      .contenBoxMain {
+        position: relative;
+        width: 100%;
+        height: 100%;
+      }
+
+      .contenBox {
+        width: 100%;
+        height: 100%;
+        position: absolute;
+        top: 0;
+        left: 0;
+        opacity: 0;
+        pointer-events: none;
+        transition: all 0.5s;
+
+        .modelBox,
+        .videoBox,
+        .imgBox {
+          width: 100%;
+          height: 100%;
+        }
+
+        .modelBox {
+          iframe {
+            width: 100%;
+            height: 100%;
+          }
+        }
+
+        .videoBox {
+          padding: 100px 100px 120px;
+
+          video {
+            width: 100%;
+            height: 100%;
+          }
+        }
+
+        .imgBox {
+          // padding: 100px 100px 120px;
+
+          .smImgBox {
+            width: 100%;
+            height: 100%;
+            cursor: zoom-in;
+
+            &>img {
+              pointer-events: none;
+              width: 100%;
+              height: 100%;
+              object-fit: contain;
+            }
+          }
+        }
+      }
+
+      .contenBoxAc {
+        opacity: 1;
+        pointer-events: auto;
+      }
+
+      .awccJJ {
+        cursor: pointer;
+        position: absolute;
+        top: 50%;
+        transform: translateY(-50%);
+        left: 10px;
+        width: 37px;
+        height: 37px;
+        background-image: url("../assets/images/pc/left.png");
+        background-size: 100% 100%;
+
+        &:focus {
+          outline: none;
+        }
+      }
+
+      .rightJJ {
+        left: auto;
+        right: 10px;
+        background-image: url("../assets/images/pc/right.png");
+      }
+
+      .noClick {
+        cursor: default;
+        opacity: 0.4;
+      }
+    }
+
+    .flooTxt {
+      margin-top: 20px;
+      width: 100%;
+      height: 160px;
+
+      .flooTxtBox {
+        width: 100%;
+        height: 100%;
+        overflow-y: auto;
+
+        .myTitle {
+          color: #fff;
+          font-size: 22px;
+          font-weight: 700;
+          margin-bottom: 10px;
+          text-align: center;
+        }
+
+        .myTxt {
+          font-size: 16px;
+          color: #ffffff;
+          line-height: 24px;
+        }
+
+        &::-webkit-scrollbar {
+          /*滚动条整体样式*/
+          width: 3px;
+          /*高宽分别对应横竖滚动条的尺寸*/
+          height: 1px;
+        }
+
+        &::-webkit-scrollbar-thumb {
+          /*滚动条里面小方块*/
+          border-radius: 10px;
+          -webkit-box-shadow: inset 0 0 5px transparent;
+          background: #EAD5A3;
+        }
+
+        &::-webkit-scrollbar-track {
+          /*滚动条里面轨道*/
+          -webkit-box-shadow: inset 0 0 5px transparent;
+          border-radius: 10px;
+          background: transparent;
+        }
+      }
+    }
+
+    .flooTxtOne {
+      height: 600px;
+    }
+  }
+}
+
+// 移动端
+@media screen and (max-width: 1000px) {
+  .home {
+    #myAudio {
+      width: 90vw;
+      max-width: 500px;
+    }
+
+    .main {
+      width: 90%;
+      height: 94%;
+      padding: 0;
+      position: absolute;
+      top: 50%;
+      left: 50%;
+      transform: translate(-50%, -50%);
+
+      .mainCon {
+        border-radius: 8px 8px 0 0;
+
+        .audioIcon {
+          cursor: default;
+          right: auto;
+          bottom: auto;
+          top: 6px;
+          left: 6px;
+
+          &>img {
+            width: 30px;
+          }
+        }
+
+        .flooTabBox {
+          width: 100%;
+          bottom: 20px;
+          justify-content: center;
+
+          .tabRow {
+            cursor: default;
+            margin: 0 6px;
+            padding: 0 10px;
+            height: 32px;
+
+            &>img {
+              width: 16px;
+            }
+          }
+        }
+
+        .contenBox {
+          .videoBox {
+            padding: 0px 0;
+            position: relative;
+
+            video {
+              width: 96%;
+              max-height: 100%;
+              height: auto;
+              position: absolute;
+              top: 50%;
+              left: 2%;
+              transform: translateY(-50%);
+            }
+          }
+
+          .imgBox {
+            // padding: 60px 50px 80px;
+
+            .smImgBox {
+              cursor: default;
+            }
+          }
+        }
+
+        .awccJJ {
+          left: 0;
+          width: 28px;
+          height: 57px;
+          cursor: default;
+          background-image: url("../assets/images/pc/icon-left.png");
+        }
+
+        .rightJJ {
+          left: auto;
+          right: 0;
+          background-image: url("../assets/images/pc/icon-right.png");
+        }
+      }
+
+      .flooTxt {
+        margin-top: 0;
+        padding: 20px 15px 15px;
+        height: 200px;
+        // background-color: #fff;
+        border-radius: 0 0 8px 8px;
+
+        .flooTxtBox {
+          .myTitle {
+            font-size: 18px;
+          }
+
+          .myTxt {
+            font-size: 14px;
+            line-height: 22px;
+          }
+        }
+      }
+
+      .flooTxtOne {
+        height: 100%;
+      }
+    }
+  }
+}</style>
+

+ 3 - 0
hot/vue.config.js

@@ -0,0 +1,3 @@
+module.exports = {
+  publicPath: "./"
+};

+ 384 - 6
houtai/package-lock.json

@@ -18,6 +18,8 @@
         "@types/react-dom": "^18.0.8",
         "antd": "^5.0.4",
         "axios": "^1.1.3",
+        "braft-editor": "^2.3.9",
+        "braft-utils": "^3.0.12",
         "dayjs": "^1.11.7",
         "echarts": "^5.4.0",
         "file-saver": "^2.0.5",
@@ -5311,6 +5313,88 @@
         "node": ">=8"
       }
     },
+    "node_modules/braft-convert": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/braft-convert/-/braft-convert-2.3.0.tgz",
+      "integrity": "sha512-5km+dLHk8iYDv2iEYDrDQ2ld/ZoUx66QLql0qdm5PqZEcNXc8dBHGLORfzeu3iMw1jLeAiHxtdY5+ypuIhczVg==",
+      "dependencies": {
+        "draft-convert": "^2.0.0",
+        "draft-js": "^0.10.3"
+      },
+      "peerDependencies": {
+        "react": "^16.0.0"
+      }
+    },
+    "node_modules/braft-convert/node_modules/draft-convert": {
+      "version": "2.1.13",
+      "resolved": "https://registry.npmmirror.com/draft-convert/-/draft-convert-2.1.13.tgz",
+      "integrity": "sha512-/h/n4JCfyO8aWby7wKBkccHdsuVbbDyHWXi/B3Zf2pN++lN1lDOIVt5ulXCcbH2Y5YJEFzMJw/YGfN+R0axxxg==",
+      "dependencies": {
+        "@babel/runtime": "^7.5.5",
+        "immutable": "~3.7.4",
+        "invariant": "^2.2.1"
+      },
+      "peerDependencies": {
+        "draft-js": ">=0.7.0",
+        "react": "^15.0.2 || ^16.0.0-rc || ^16.0.0 || ^17.0.0 || ^18.0.0",
+        "react-dom": "^15.0.2 || ^16.0.0-rc || ^16.0.0 || ^17.0.0 || ^18.0.0"
+      }
+    },
+    "node_modules/braft-editor": {
+      "version": "2.3.9",
+      "resolved": "https://registry.npmmirror.com/braft-editor/-/braft-editor-2.3.9.tgz",
+      "integrity": "sha512-mqdPk/zI2dhFK8tW/A4Qj/AkkARLh5L/niNw+iif5wFqb6zh15rMlrShgz1nWO/QXyAKr8XtDgxiBbR0zWwtRg==",
+      "dependencies": {
+        "@babel/runtime": "^7.0.0",
+        "braft-convert": "^2.3.0",
+        "braft-finder": "^0.0.19",
+        "braft-utils": "^3.0.8",
+        "draft-convert": "^2.0.0",
+        "draft-js": "^0.10.3",
+        "draft-js-multidecorators": "^1.0.0",
+        "draftjs-utils": "^0.9.4",
+        "immutable": "~3.7.4"
+      },
+      "peerDependencies": {
+        "react": "^15.0.2|| ^16.0.0-rc || ^16.0.0",
+        "react-dom": "^15.0.2|| ^16.0.0-rc || ^16.0.0"
+      }
+    },
+    "node_modules/braft-editor/node_modules/braft-finder": {
+      "version": "0.0.19",
+      "resolved": "https://registry.npmmirror.com/braft-finder/-/braft-finder-0.0.19.tgz",
+      "integrity": "sha512-0kzI6/KbomJJhYX1hpjn4edCKhblyUyWdUrsgBmOrwy0vrj+pPkm69+Uf8Uj6KGAULM6LF0ooC++p7fqUGgFHw==",
+      "peerDependencies": {
+        "react": "^16.4.1",
+        "react-dom": "^16.4.1"
+      }
+    },
+    "node_modules/braft-editor/node_modules/draft-convert": {
+      "version": "2.1.13",
+      "resolved": "https://registry.npmmirror.com/draft-convert/-/draft-convert-2.1.13.tgz",
+      "integrity": "sha512-/h/n4JCfyO8aWby7wKBkccHdsuVbbDyHWXi/B3Zf2pN++lN1lDOIVt5ulXCcbH2Y5YJEFzMJw/YGfN+R0axxxg==",
+      "dependencies": {
+        "@babel/runtime": "^7.5.5",
+        "immutable": "~3.7.4",
+        "invariant": "^2.2.1"
+      },
+      "peerDependencies": {
+        "draft-js": ">=0.7.0",
+        "react": "^15.0.2 || ^16.0.0-rc || ^16.0.0 || ^17.0.0 || ^18.0.0",
+        "react-dom": "^15.0.2 || ^16.0.0-rc || ^16.0.0 || ^17.0.0 || ^18.0.0"
+      }
+    },
+    "node_modules/braft-utils": {
+      "version": "3.0.12",
+      "resolved": "https://registry.npmmirror.com/braft-utils/-/braft-utils-3.0.12.tgz",
+      "integrity": "sha512-O2cKysURNC4HSEMKgNmQ2RluwcrxvYrztlEmyPN5SzktiNX3vaLFQoo0Ez3PlIhvjaGrIBSIT2Oyh2N6mn6TFg==",
+      "peerDependencies": {
+        "braft-convert": "^2.1.4",
+        "draft-js": "^0.10.5",
+        "draftjs-utils": "^0.9.4",
+        "immutable": "~3.7.4"
+      }
+    },
     "node_modules/browser-process-hrtime": {
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz",
@@ -6641,6 +6725,37 @@
       "resolved": "https://registry.npmmirror.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
       "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA=="
     },
+    "node_modules/draft-js": {
+      "version": "0.10.5",
+      "resolved": "https://registry.npmmirror.com/draft-js/-/draft-js-0.10.5.tgz",
+      "integrity": "sha512-LE6jSCV9nkPhfVX2ggcRLA4FKs6zWq9ceuO/88BpXdNCS7mjRTgs0NsV6piUCJX9YxMsB9An33wnkMmU2sD2Zg==",
+      "dependencies": {
+        "fbjs": "^0.8.15",
+        "immutable": "~3.7.4",
+        "object-assign": "^4.1.0"
+      },
+      "peerDependencies": {
+        "react": "^0.14.0 || ^15.0.0-rc || ^16.0.0-rc || ^16.0.0",
+        "react-dom": "^0.14.0 || ^15.0.0-rc || ^16.0.0-rc || ^16.0.0"
+      }
+    },
+    "node_modules/draft-js-multidecorators": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/draft-js-multidecorators/-/draft-js-multidecorators-1.0.0.tgz",
+      "integrity": "sha512-7qdy+YQol5iq38AoEerhgSJWhCzxvZLn1x5ODfUlGfWlg0SrZ9AXJbaxHVIjdSIZNrbVIm+WANujNxMqCmDSZQ==",
+      "dependencies": {
+        "immutable": "*"
+      }
+    },
+    "node_modules/draftjs-utils": {
+      "version": "0.9.4",
+      "resolved": "https://registry.npmmirror.com/draftjs-utils/-/draftjs-utils-0.9.4.tgz",
+      "integrity": "sha512-KYjABSbGpJrwrwmxVj5UhfV37MF/p0QRxKIyL+/+QOaJ8J9z1FBKxkblThbpR0nJi9lxPQWGg+gh+v0dAsSCCg==",
+      "peerDependencies": {
+        "draft-js": "^0.10.x",
+        "immutable": "3.x.x || 4.x.x"
+      }
+    },
     "node_modules/duplexer": {
       "version": "0.1.2",
       "resolved": "https://registry.npmmirror.com/duplexer/-/duplexer-0.1.2.tgz",
@@ -6713,6 +6828,14 @@
         "node": ">= 0.8"
       }
     },
+    "node_modules/encoding": {
+      "version": "0.1.13",
+      "resolved": "https://registry.npmmirror.com/encoding/-/encoding-0.1.13.tgz",
+      "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
+      "dependencies": {
+        "iconv-lite": "^0.6.2"
+      }
+    },
     "node_modules/enhanced-resolve": {
       "version": "5.10.0",
       "resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz",
@@ -7758,6 +7881,34 @@
         "bser": "2.1.1"
       }
     },
+    "node_modules/fbjs": {
+      "version": "0.8.18",
+      "resolved": "https://registry.npmmirror.com/fbjs/-/fbjs-0.8.18.tgz",
+      "integrity": "sha512-EQaWFK+fEPSoibjNy8IxUtaFOMXcWsY0JaVrQoZR9zC8N2Ygf9iDITPWjUTVIax95b6I742JFLqASHfsag/vKA==",
+      "dependencies": {
+        "core-js": "^1.0.0",
+        "isomorphic-fetch": "^2.1.1",
+        "loose-envify": "^1.0.0",
+        "object-assign": "^4.1.0",
+        "promise": "^7.1.1",
+        "setimmediate": "^1.0.5",
+        "ua-parser-js": "^0.7.30"
+      }
+    },
+    "node_modules/fbjs/node_modules/core-js": {
+      "version": "1.2.7",
+      "resolved": "https://registry.npmmirror.com/core-js/-/core-js-1.2.7.tgz",
+      "integrity": "sha512-ZiPp9pZlgxpWRu0M+YWbm6+aQ84XEfH1JRXvfOc/fILWI0VKhLC2LX13X1NYq4fULzLMq7Hfh43CSo2/aIaUPA==",
+      "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js."
+    },
+    "node_modules/fbjs/node_modules/promise": {
+      "version": "7.3.1",
+      "resolved": "https://registry.npmmirror.com/promise/-/promise-7.3.1.tgz",
+      "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+      "dependencies": {
+        "asap": "~2.0.3"
+      }
+    },
     "node_modules/fflate": {
       "version": "0.4.8",
       "resolved": "https://registry.npmmirror.com/fflate/-/fflate-0.4.8.tgz",
@@ -8724,9 +8875,12 @@
       "integrity": "sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ=="
     },
     "node_modules/immutable": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmmirror.com/immutable/-/immutable-4.1.0.tgz",
-      "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ=="
+      "version": "3.7.6",
+      "resolved": "https://registry.npmmirror.com/immutable/-/immutable-3.7.6.tgz",
+      "integrity": "sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==",
+      "engines": {
+        "node": ">=0.8.0"
+      }
     },
     "node_modules/import-fresh": {
       "version": "3.3.0",
@@ -8816,6 +8970,14 @@
       "resolved": "https://registry.npmmirror.com/intersection-observer/-/intersection-observer-0.12.2.tgz",
       "integrity": "sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg=="
     },
+    "node_modules/invariant": {
+      "version": "2.2.4",
+      "resolved": "https://registry.npmmirror.com/invariant/-/invariant-2.2.4.tgz",
+      "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+      "dependencies": {
+        "loose-envify": "^1.0.0"
+      }
+    },
     "node_modules/ipaddr.js": {
       "version": "2.0.1",
       "resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz",
@@ -9145,6 +9307,15 @@
       "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz",
       "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
     },
+    "node_modules/isomorphic-fetch": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmmirror.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
+      "integrity": "sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==",
+      "dependencies": {
+        "node-fetch": "^1.0.1",
+        "whatwg-fetch": ">=0.10.0"
+      }
+    },
     "node_modules/istanbul-lib-coverage": {
       "version": "3.2.0",
       "resolved": "https://registry.npmmirror.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
@@ -11812,6 +11983,23 @@
         "tslib": "^2.0.3"
       }
     },
+    "node_modules/node-fetch": {
+      "version": "1.7.3",
+      "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-1.7.3.tgz",
+      "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
+      "dependencies": {
+        "encoding": "^0.1.11",
+        "is-stream": "^1.0.1"
+      }
+    },
+    "node_modules/node-fetch/node_modules/is-stream": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-1.1.0.tgz",
+      "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/node-forge": {
       "version": "1.3.1",
       "resolved": "https://registry.npmmirror.com/node-forge/-/node-forge-1.3.1.tgz",
@@ -15217,6 +15405,11 @@
         }
       }
     },
+    "node_modules/sass/node_modules/immutable": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmmirror.com/immutable/-/immutable-4.3.4.tgz",
+      "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA=="
+    },
     "node_modules/sax": {
       "version": "1.2.4",
       "resolved": "https://registry.npmmirror.com/sax/-/sax-1.2.4.tgz",
@@ -15433,6 +15626,11 @@
         "node": ">= 0.8.0"
       }
     },
+    "node_modules/setimmediate": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmmirror.com/setimmediate/-/setimmediate-1.0.5.tgz",
+      "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
+    },
     "node_modules/setprototypeof": {
       "version": "1.2.0",
       "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz",
@@ -16381,6 +16579,14 @@
         "node": ">=4.2.0"
       }
     },
+    "node_modules/ua-parser-js": {
+      "version": "0.7.37",
+      "resolved": "https://registry.npmmirror.com/ua-parser-js/-/ua-parser-js-0.7.37.tgz",
+      "integrity": "sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA==",
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/unbox-primitive": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
@@ -21488,6 +21694,67 @@
         "fill-range": "^7.0.1"
       }
     },
+    "braft-convert": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/braft-convert/-/braft-convert-2.3.0.tgz",
+      "integrity": "sha512-5km+dLHk8iYDv2iEYDrDQ2ld/ZoUx66QLql0qdm5PqZEcNXc8dBHGLORfzeu3iMw1jLeAiHxtdY5+ypuIhczVg==",
+      "requires": {
+        "draft-convert": "^2.0.0",
+        "draft-js": "^0.10.3"
+      },
+      "dependencies": {
+        "draft-convert": {
+          "version": "2.1.13",
+          "resolved": "https://registry.npmmirror.com/draft-convert/-/draft-convert-2.1.13.tgz",
+          "integrity": "sha512-/h/n4JCfyO8aWby7wKBkccHdsuVbbDyHWXi/B3Zf2pN++lN1lDOIVt5ulXCcbH2Y5YJEFzMJw/YGfN+R0axxxg==",
+          "requires": {
+            "@babel/runtime": "^7.5.5",
+            "immutable": "~3.7.4",
+            "invariant": "^2.2.1"
+          }
+        }
+      }
+    },
+    "braft-editor": {
+      "version": "2.3.9",
+      "resolved": "https://registry.npmmirror.com/braft-editor/-/braft-editor-2.3.9.tgz",
+      "integrity": "sha512-mqdPk/zI2dhFK8tW/A4Qj/AkkARLh5L/niNw+iif5wFqb6zh15rMlrShgz1nWO/QXyAKr8XtDgxiBbR0zWwtRg==",
+      "requires": {
+        "@babel/runtime": "^7.0.0",
+        "braft-convert": "^2.3.0",
+        "braft-finder": "^0.0.19",
+        "braft-utils": "^3.0.8",
+        "draft-convert": "^2.0.0",
+        "draft-js": "^0.10.3",
+        "draft-js-multidecorators": "^1.0.0",
+        "draftjs-utils": "^0.9.4",
+        "immutable": "~3.7.4"
+      },
+      "dependencies": {
+        "braft-finder": {
+          "version": "0.0.19",
+          "resolved": "https://registry.npmmirror.com/braft-finder/-/braft-finder-0.0.19.tgz",
+          "integrity": "sha512-0kzI6/KbomJJhYX1hpjn4edCKhblyUyWdUrsgBmOrwy0vrj+pPkm69+Uf8Uj6KGAULM6LF0ooC++p7fqUGgFHw==",
+          "requires": {}
+        },
+        "draft-convert": {
+          "version": "2.1.13",
+          "resolved": "https://registry.npmmirror.com/draft-convert/-/draft-convert-2.1.13.tgz",
+          "integrity": "sha512-/h/n4JCfyO8aWby7wKBkccHdsuVbbDyHWXi/B3Zf2pN++lN1lDOIVt5ulXCcbH2Y5YJEFzMJw/YGfN+R0axxxg==",
+          "requires": {
+            "@babel/runtime": "^7.5.5",
+            "immutable": "~3.7.4",
+            "invariant": "^2.2.1"
+          }
+        }
+      }
+    },
+    "braft-utils": {
+      "version": "3.0.12",
+      "resolved": "https://registry.npmmirror.com/braft-utils/-/braft-utils-3.0.12.tgz",
+      "integrity": "sha512-O2cKysURNC4HSEMKgNmQ2RluwcrxvYrztlEmyPN5SzktiNX3vaLFQoo0Ez3PlIhvjaGrIBSIT2Oyh2N6mn6TFg==",
+      "requires": {}
+    },
     "browser-process-hrtime": {
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz",
@@ -22533,6 +22800,30 @@
       "resolved": "https://registry.npmmirror.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
       "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA=="
     },
+    "draft-js": {
+      "version": "0.10.5",
+      "resolved": "https://registry.npmmirror.com/draft-js/-/draft-js-0.10.5.tgz",
+      "integrity": "sha512-LE6jSCV9nkPhfVX2ggcRLA4FKs6zWq9ceuO/88BpXdNCS7mjRTgs0NsV6piUCJX9YxMsB9An33wnkMmU2sD2Zg==",
+      "requires": {
+        "fbjs": "^0.8.15",
+        "immutable": "~3.7.4",
+        "object-assign": "^4.1.0"
+      }
+    },
+    "draft-js-multidecorators": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/draft-js-multidecorators/-/draft-js-multidecorators-1.0.0.tgz",
+      "integrity": "sha512-7qdy+YQol5iq38AoEerhgSJWhCzxvZLn1x5ODfUlGfWlg0SrZ9AXJbaxHVIjdSIZNrbVIm+WANujNxMqCmDSZQ==",
+      "requires": {
+        "immutable": "*"
+      }
+    },
+    "draftjs-utils": {
+      "version": "0.9.4",
+      "resolved": "https://registry.npmmirror.com/draftjs-utils/-/draftjs-utils-0.9.4.tgz",
+      "integrity": "sha512-KYjABSbGpJrwrwmxVj5UhfV37MF/p0QRxKIyL+/+QOaJ8J9z1FBKxkblThbpR0nJi9lxPQWGg+gh+v0dAsSCCg==",
+      "requires": {}
+    },
     "duplexer": {
       "version": "0.1.2",
       "resolved": "https://registry.npmmirror.com/duplexer/-/duplexer-0.1.2.tgz",
@@ -22592,6 +22883,14 @@
       "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz",
       "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
     },
+    "encoding": {
+      "version": "0.1.13",
+      "resolved": "https://registry.npmmirror.com/encoding/-/encoding-0.1.13.tgz",
+      "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
+      "requires": {
+        "iconv-lite": "^0.6.2"
+      }
+    },
     "enhanced-resolve": {
       "version": "5.10.0",
       "resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz",
@@ -23418,6 +23717,35 @@
         "bser": "2.1.1"
       }
     },
+    "fbjs": {
+      "version": "0.8.18",
+      "resolved": "https://registry.npmmirror.com/fbjs/-/fbjs-0.8.18.tgz",
+      "integrity": "sha512-EQaWFK+fEPSoibjNy8IxUtaFOMXcWsY0JaVrQoZR9zC8N2Ygf9iDITPWjUTVIax95b6I742JFLqASHfsag/vKA==",
+      "requires": {
+        "core-js": "^1.0.0",
+        "isomorphic-fetch": "^2.1.1",
+        "loose-envify": "^1.0.0",
+        "object-assign": "^4.1.0",
+        "promise": "^7.1.1",
+        "setimmediate": "^1.0.5",
+        "ua-parser-js": "^0.7.30"
+      },
+      "dependencies": {
+        "core-js": {
+          "version": "1.2.7",
+          "resolved": "https://registry.npmmirror.com/core-js/-/core-js-1.2.7.tgz",
+          "integrity": "sha512-ZiPp9pZlgxpWRu0M+YWbm6+aQ84XEfH1JRXvfOc/fILWI0VKhLC2LX13X1NYq4fULzLMq7Hfh43CSo2/aIaUPA=="
+        },
+        "promise": {
+          "version": "7.3.1",
+          "resolved": "https://registry.npmmirror.com/promise/-/promise-7.3.1.tgz",
+          "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+          "requires": {
+            "asap": "~2.0.3"
+          }
+        }
+      }
+    },
     "fflate": {
       "version": "0.4.8",
       "resolved": "https://registry.npmmirror.com/fflate/-/fflate-0.4.8.tgz",
@@ -24170,9 +24498,9 @@
       "integrity": "sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ=="
     },
     "immutable": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmmirror.com/immutable/-/immutable-4.1.0.tgz",
-      "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ=="
+      "version": "3.7.6",
+      "resolved": "https://registry.npmmirror.com/immutable/-/immutable-3.7.6.tgz",
+      "integrity": "sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw=="
     },
     "import-fresh": {
       "version": "3.3.0",
@@ -24243,6 +24571,14 @@
       "resolved": "https://registry.npmmirror.com/intersection-observer/-/intersection-observer-0.12.2.tgz",
       "integrity": "sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg=="
     },
+    "invariant": {
+      "version": "2.2.4",
+      "resolved": "https://registry.npmmirror.com/invariant/-/invariant-2.2.4.tgz",
+      "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+      "requires": {
+        "loose-envify": "^1.0.0"
+      }
+    },
     "ipaddr.js": {
       "version": "2.0.1",
       "resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz",
@@ -24494,6 +24830,15 @@
       "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz",
       "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
     },
+    "isomorphic-fetch": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmmirror.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
+      "integrity": "sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==",
+      "requires": {
+        "node-fetch": "^1.0.1",
+        "whatwg-fetch": ">=0.10.0"
+      }
+    },
     "istanbul-lib-coverage": {
       "version": "3.2.0",
       "resolved": "https://registry.npmmirror.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
@@ -26575,6 +26920,22 @@
         "tslib": "^2.0.3"
       }
     },
+    "node-fetch": {
+      "version": "1.7.3",
+      "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-1.7.3.tgz",
+      "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
+      "requires": {
+        "encoding": "^0.1.11",
+        "is-stream": "^1.0.1"
+      },
+      "dependencies": {
+        "is-stream": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-1.1.0.tgz",
+          "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ=="
+        }
+      }
+    },
     "node-forge": {
       "version": "1.3.1",
       "resolved": "https://registry.npmmirror.com/node-forge/-/node-forge-1.3.1.tgz",
@@ -28961,6 +29322,13 @@
         "chokidar": ">=3.0.0 <4.0.0",
         "immutable": "^4.0.0",
         "source-map-js": ">=0.6.2 <2.0.0"
+      },
+      "dependencies": {
+        "immutable": {
+          "version": "4.3.4",
+          "resolved": "https://registry.npmmirror.com/immutable/-/immutable-4.3.4.tgz",
+          "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA=="
+        }
       }
     },
     "sass-loader": {
@@ -29161,6 +29529,11 @@
         "send": "0.18.0"
       }
     },
+    "setimmediate": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmmirror.com/setimmediate/-/setimmediate-1.0.5.tgz",
+      "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
+    },
     "setprototypeof": {
       "version": "1.2.0",
       "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz",
@@ -29918,6 +30291,11 @@
       "resolved": "https://registry.npmmirror.com/typescript/-/typescript-4.8.4.tgz",
       "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ=="
     },
+    "ua-parser-js": {
+      "version": "0.7.37",
+      "resolved": "https://registry.npmmirror.com/ua-parser-js/-/ua-parser-js-0.7.37.tgz",
+      "integrity": "sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA=="
+    },
     "unbox-primitive": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz",

+ 2 - 0
houtai/package.json

@@ -13,6 +13,8 @@
     "@types/react-dom": "^18.0.8",
     "antd": "^5.0.4",
     "axios": "^1.1.3",
+    "braft-editor": "^2.3.9",
+    "braft-utils": "^3.0.12",
     "dayjs": "^1.11.7",
     "echarts": "^5.4.0",
     "file-saver": "^2.0.5",

+ 53 - 0
houtai/src/components/Z_RichText/index.module.scss

@@ -0,0 +1,53 @@
+.RichText {
+  :global {
+    .txtBox {
+      width: 800px;
+      border: 1px solid #ccc;
+
+      // 隐藏媒体功能
+      .control-item.media {
+        display: none;
+      }
+
+      .bf-controlbar {
+        position: relative;
+
+        .upImgBox {
+          position: absolute;
+          bottom: 13px;
+          right: 15px;
+          cursor: pointer;
+          color: var(--themeColor);
+        }
+
+        .upImgBoxNo {
+          display: none;
+        }
+
+      }
+    }
+
+    .noUpThumb {
+      position: relative;
+      overflow: hidden;
+      opacity: 0;
+      transition: top .2s;
+      color: #ff4d4f;
+      top: -10px;
+    }
+
+    .noUpThumbAc {
+      top: 0;
+      opacity: 1;
+    }
+
+    .bf-media .bf-image {
+      float: initial !important;
+      display: block;
+      margin: 10px auto;
+      max-width: 500px;
+      max-height: 500px;
+    }
+
+  }
+}

+ 194 - 0
houtai/src/components/Z_RichText/index.tsx

@@ -0,0 +1,194 @@
+import React, {
+  useCallback,
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+} from "react";
+import styles from "./index.module.scss";
+
+// 引入编辑器组件
+
+// 安装---npm install braft-editor --save --force
+// npm install braft-utils --save --force
+import { ContentUtils } from "braft-utils";
+import BraftEditor from "braft-editor";
+// 引入编辑器样式
+import "braft-editor/dist/index.css";
+
+import classNames from "classnames";
+import { MessageFu } from "@/utils/message";
+import { fileDomInitialFu } from "@/utils/domShow";
+import { baseURL } from "@/utils/http";
+
+import { forwardRef, useImperativeHandle } from "react";
+// import { A1_APIupFile } from "@/store/action/A1Plate";
+
+type Props = {
+  check: boolean; //表单校验,为fasle表示不校验
+  dirCode: string; //文件的code码
+  isLook: boolean; //是否是查看进来
+  ref: any; //当前自己的ref,给父组件调用
+  myUrl: string; //上传的api地址
+};
+
+function RichText({ check, dirCode, isLook, myUrl }: Props, ref: any) {
+  // 添加 上传 图片的dom
+  useEffect(() => {
+    if (!isLook) {
+      setTimeout(() => {
+        const dom = document.querySelector(".bf-controlbar")!;
+        const div = document.createElement("div");
+        div.className = "upImgBox";
+        // div.title = "上传图片";
+        div.innerHTML = "上传图片";
+        div.onclick = async () => {
+          myInput.current?.click();
+        };
+        dom.appendChild(div);
+      }, 200);
+
+      // 监听 富文本 的 class 变化,在全屏的时候会 富文本会添加上 fullscreen 的类
+      // 修复顶部样式冲突问题
+
+      const editorDom = document.querySelector(
+        ".bf-container"
+      ) as HTMLDivElement;
+
+      const observer = new MutationObserver(() => {
+        // console.log("change");
+        const dom = document.querySelector(".layoutRightTop") as HTMLDivElement;
+
+        if (editorDom.className.includes("fullscreen")) dom.style.zIndex = "-1";
+        else dom.style.zIndex = "100";
+      });
+
+      observer.observe(editorDom, {
+        attributes: true,
+      });
+
+      // 销毁监听
+      return () => {
+        observer.disconnect();
+      };
+    }
+  }, [isLook]);
+
+  // 编辑器文本
+  const [editorValue, setEditorValue] = useState(
+    // 初始内容
+    BraftEditor.createEditorState("")
+  );
+
+  // 判断 富文本是否为空
+  const isTxtFlag = useMemo(() => {
+    const txt: string = editorValue.toHTML();
+    if (
+      txt.replaceAll("<p>", "").replaceAll("</p>", "").replaceAll(" ", "") ===
+      ""
+    ) {
+      return true;
+    } else return false;
+  }, [editorValue]);
+
+  const myInput = useRef<HTMLInputElement>(null);
+
+  // 上传图片
+  const handeUpPhoto = useCallback(
+    async (e: React.ChangeEvent<HTMLInputElement>) => {
+      if (e.target.files) {
+        // 拿到files信息
+        const filesInfo = e.target.files[0];
+        // 校验格式
+        const type = ["image/jpeg", "image/png"];
+        if (!type.includes(filesInfo.type)) {
+          e.target.value = "";
+          return MessageFu.warning("只支持png、jpg和jpeg格式!");
+        }
+        // 校验大小
+        if (filesInfo.size > 5 * 1024 * 1024) {
+          e.target.value = "";
+          return MessageFu.warning("最大支持5M!");
+        }
+        // 创建FormData对象
+        const fd = new FormData();
+        // 把files添加进FormData对象(‘photo’为后端需要的字段)
+        fd.append("type", "img");
+        fd.append("dirCode", dirCode);
+        fd.append("file", filesInfo);
+
+        e.target.value = "";
+
+        try {
+          // const res = await A1_APIupFile(fd, myUrl);
+          // if (res.code === 0) {
+          //   MessageFu.success("上传成功!");
+          //   // 在光标位置插入图片
+          //   const newTxt = ContentUtils.insertMedias(editorValue, [
+          //     {
+          //       type: "IMAGE",
+          //       url: baseURL + res.data.filePath,
+          //     },
+          //   ]);
+
+          //   setEditorValue(newTxt);
+          // }
+          fileDomInitialFu();
+        } catch (error) {
+          fileDomInitialFu();
+        }
+      }
+    },
+    [dirCode]
+  );
+
+  // 让父组件调用的 回显 富文本
+  const ritxtShowFu = useCallback((val: string) => {
+    setEditorValue(BraftEditor.createEditorState(val));
+  }, []);
+
+  // 让父组件调用的返回 富文本信息 和 表单校验
+  const fatherBtnOkFu = useCallback(() => {
+    return { val: editorValue.toHTML(), flag: isTxtFlag };
+  }, [editorValue, isTxtFlag]);
+
+  // 可以让父组件调用子组件的方法
+  useImperativeHandle(ref, () => ({
+    ritxtShowFu,
+    fatherBtnOkFu,
+  }));
+
+  return (
+    <div className={styles.RichText}>
+      <input
+        id="upInput"
+        type="file"
+        accept=".png,.jpg,.jpeg"
+        ref={myInput}
+        onChange={(e) => handeUpPhoto(e)}
+      />
+
+      <div className="txtBox">
+        <BraftEditor
+          readOnly={isLook}
+          placeholder="请输入内容"
+          value={editorValue}
+          onChange={(e:any) => setEditorValue(e)}
+          imageControls={["remove"]}
+        />
+      </div>
+      <div
+        className={classNames(
+          "noUpThumb",
+          check && isTxtFlag ? "noUpThumbAc" : ""
+        )}
+      >
+        请输入正文!
+      </div>
+    </div>
+  );
+}
+
+// const MemoRichText = React.memo(RichText);
+
+export default forwardRef(RichText);

+ 19 - 0
houtai/src/pages/A1Rule/RuleEdit/index.module.scss

@@ -0,0 +1,19 @@
+.RuleEdit {
+  :global {
+    .ant-modal-close {
+      display: none;
+    }
+
+    .userAddMain {
+      border-top: 1px solid #999999;
+      padding-top: 15px;
+      width: 100%;
+
+      .passTit {
+        color: #ff4d4f;
+        font-size: 14px;
+        padding-left: 98px;
+      }
+    }
+  }
+}

+ 237 - 0
houtai/src/pages/A1Rule/RuleEdit/index.tsx

@@ -0,0 +1,237 @@
+import { getRuleInfoByIdAPI, ruleSaveAPI } from "@/store/action/A1Rule";
+import { SaveRuleType } from "@/types";
+import { MessageFu } from "@/utils/message";
+import { Button, Form, FormInstance, Input, Modal, Popconfirm } from "antd";
+import React, { useCallback, useEffect, useRef, useState } from "react";
+import styles from "./index.module.scss";
+import RichText from "@/components/Z_RichText";
+
+type Props = {
+  id: any;
+  closePage: () => void;
+  upTableList: () => void;
+  editMode: number;
+};
+
+function RuleEdit({ id, closePage, upTableList, editMode }: Props) {
+  // 设置表单初始数据(区分编辑和新增)
+  const FormBoxRef = useRef<FormInstance>(null);
+
+  const currentIdInfo = useRef(null);
+
+  // 富文本的ref
+  const richTxtRef = useRef<any>(null);
+
+  // 文件的校验
+  const [check, setCheck] = useState(false);
+
+  // 文件的code码
+  const [dirCode, setDirCode] = useState("");
+
+  const getInfoInAPIFu = useCallback(async (id: number) => {
+    const res = await getRuleInfoByIdAPI(id);
+    FormBoxRef.current?.setFieldsValue(res.data);
+
+    // 富文本回显
+    richTxtRef.current.ritxtShowFu(res.data.content);
+    currentIdInfo.current = res.data;
+  }, []);
+
+  // 没有通过校验
+  const onFinishFailed = useCallback(() => {
+    // return MessageFu.warning("有表单不符号规则!");
+  }, []);
+
+  useEffect(() => {
+    if (id) getInfoInAPIFu(id);
+    else {
+      FormBoxRef.current?.setFieldsValue({});
+    }
+  }, [getInfoInAPIFu, id]);
+
+  // 通过校验点击确定
+  const onFinish = useCallback(
+    async (values: any) => {
+      const obj: SaveRuleType = {
+        ...values,
+        id: id ? id : null,
+      };
+
+      const res: any = await ruleSaveAPI(obj);
+
+      if (res.code === 0) {
+        MessageFu.success(id ? "编辑成功!" : "新增成功!");
+        if (id) upTableList();
+        else;
+
+        closePage();
+      }
+      console.log("通过校验,点击确定");
+    },
+    [closePage, id, upTableList]
+  );
+
+  return (
+    <>
+      {editMode === 1 ? (
+        <Modal
+          wrapClassName={styles.RuleEdit}
+          destroyOnClose
+          open={true}
+          // title={currentIdInfo ? currentIdInfo : "编辑"}
+          title="编辑"
+          footer={
+            [] // 设置footer为空,去掉 取消 确定默认按钮
+          }
+        >
+          <div className="userAddMain">
+            <Form
+              ref={FormBoxRef}
+              name="basic"
+              labelCol={{ span: 5 }}
+              onFinish={onFinish}
+              onFinishFailed={onFinishFailed}
+              autoComplete="off"
+            >
+              <Form.Item
+                label="时限(秒)"
+                name="time"
+                rules={[{ required: true, message: "请输入时限!" }]}
+                getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+              >
+                <Input
+                  disabled={id}
+                  maxLength={3}
+                  showCount
+                  placeholder="请输入数字,1-300"
+                />
+              </Form.Item>
+
+              <Form.Item
+                label="得分"
+                name="score"
+                rules={[{ required: true, message: "请输入游戏得分!" }]}
+                getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+              >
+                <Input
+                  maxLength={6}
+                  showCount
+                  placeholder="请输入数字,1-99999"
+                />
+              </Form.Item>
+
+              <Form.Item
+                label="得分说明"
+                name="specification"
+                rules={[{ required: true, message: "请输入得分说明!" }]}
+                getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+              >
+                {/* <Input maxLength={8} showCount placeholder="请输入内容" /> */}
+                <span>currentIdInfo.specification</span>
+              </Form.Item>
+
+              <Form.Item
+                label="游戏规则"
+                name="gameRule"
+                getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+              >
+                <RichText
+                  myUrl="cms/goods/upload"
+                  ref={richTxtRef}
+                  check={check}
+                  dirCode={dirCode}
+                  isLook={true}
+                />
+              </Form.Item>
+
+              {/* {id ? null : <div className="passTit">* 默认密码 123456</div>} */}
+
+              {/* 确定和取消按钮 */}
+              <br />
+              <Form.Item wrapperCol={{ offset: 9, span: 16 }}>
+                <Button type="primary" htmlType="submit">
+                  提交
+                </Button>
+                &emsp;
+                <Popconfirm
+                  title="放弃编辑后,信息将不会保存!"
+                  okText="放弃"
+                  cancelText="取消"
+                  onConfirm={closePage}
+                  okButtonProps={{ loading: false }}
+                >
+                  <Button>取消</Button>
+                </Popconfirm>
+              </Form.Item>
+            </Form>
+          </div>
+        </Modal>
+      ) : (
+        <Modal
+          wrapClassName={styles.RuleEdit}
+          destroyOnClose
+          open={true}
+          title="观看视频"
+          footer={
+            [] // 设置footer为空,去掉 取消 确定默认按钮
+          }
+        >
+          <div className="userAddMain">
+            <Form
+              ref={FormBoxRef}
+              name="basic"
+              labelCol={{ span: 5 }}
+              onFinish={onFinish}
+              onFinishFailed={onFinishFailed}
+              autoComplete="off"
+            >
+              <Form.Item
+                label="得分"
+                name="score"
+                rules={[{ required: true, message: "请输入游戏得分!" }]}
+                getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+              >
+                <Input
+                  maxLength={6}
+                  showCount
+                  placeholder="请输入数字,1-99999"
+                />
+              </Form.Item>
+
+              <Form.Item
+                label="得分说明"
+                name="specification"
+                rules={[{ required: true, message: "请输入得分说明!" }]}
+                getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+              >
+                {/* <Input maxLength={8} showCount placeholder="请输入内容" /> */}
+                <span>currentIdInfo.specification</span>
+              </Form.Item>
+              {/* 确定和取消按钮 */}
+              <br />
+              <Form.Item wrapperCol={{ offset: 9, span: 16 }}>
+                <Button type="primary" htmlType="submit">
+                  提交
+                </Button>
+                &emsp;
+                <Popconfirm
+                  title="放弃编辑后,信息将不会保存!"
+                  okText="放弃"
+                  cancelText="取消"
+                  onConfirm={closePage}
+                  okButtonProps={{ loading: false }}
+                >
+                  <Button>取消</Button>
+                </Popconfirm>
+              </Form.Item>
+            </Form>
+          </div>
+        </Modal>
+      )}
+    </>
+  );
+}
+
+const MemoRuleEdit = React.memo(RuleEdit);
+
+export default MemoRuleEdit;

+ 63 - 0
houtai/src/pages/A1Rule/TopicSetting/index.module.scss

@@ -0,0 +1,63 @@
+.TopicSetting {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  background-color: rgb(239, 239, 239);
+
+  :global {
+    .ruleTop {
+      border-radius: 4px;
+      padding: 15px 20px 25px 20px;
+      background-color: #fff;
+      box-shadow: 3px 0px 10px 0px #d5d5d9;
+      height: 100%;
+
+
+      .toprule {
+        display: flex;
+        justify-content: space-between;
+        align-items: start;
+        margin-bottom: 10px;
+
+        .pageTitle {
+          .exportBtn {
+            width: 100px;
+            height: 40px;
+          }
+        }
+
+        .addTopicBtn {
+          // position: absolute;
+          // right: 2.5%;
+          // top: 3%;
+          // height: 30px;
+          cursor: pointer;
+          margin-left: 20px;
+          // transform: translateY(-50%);
+        }
+      }
+
+
+
+      .tableBox1 {
+        border-radius: 4px;
+        overflow: hidden;
+        margin-top: -10px;
+        padding: 0px;
+
+        .ant-table-body {
+          height: 600px;
+          overflow-y: auto !important;
+          overflow-y: overlay !important;
+
+          .ant-table-row {
+            .ant-table-cell {
+              padding: 10px;
+            }
+          }
+        }
+      }
+    }
+  }
+}

+ 115 - 0
houtai/src/pages/A1Rule/TopicSetting/index.tsx

@@ -0,0 +1,115 @@
+import React, { useMemo, useRef, useState } from "react";
+import styles from "./index.module.scss";
+import { Button, Popconfirm, Table } from "antd";
+import { useSelector } from "react-redux";
+import { RootState } from "@/store";
+type Props = {
+  closeFu: () => void;
+};
+function TopicSetting({ closeFu }: Props) {
+  const pageNumRef = useRef(1);
+  const pagePageRef = useRef(10);
+  // 筛选和分页
+  const [tableSelect, setTableSelect] = useState({
+    searchKey: "",
+    pageSize: 10,
+    pageNum: 1,
+    startTime: "",
+    endTime: "",
+  });
+
+  // 页码变化
+  const paginationChange = (pageNum: number, pageSize: number) => {
+    pageNumRef.current = pageNum;
+    pagePageRef.current = pageSize;
+    setTableSelect({ ...tableSelect, pageNum, pageSize });
+  };
+
+  const results = useSelector((state: RootState) => state.A7Log.tableInfo);
+
+  const columns = useMemo(() => {
+    return [
+      {
+        width: 100,
+        title: "序号",
+        render: (text: any, record: any, index: any) =>
+          index + 1 + (pageNumRef.current - 1) * pagePageRef.current,
+      },
+      {
+        title: "时间",
+        dataIndex: "createTime",
+      },
+      {
+        title: "类型",
+        dataIndex: "type",
+      },
+      {
+        title: "积分",
+        dataIndex: "type",
+      },
+      {
+        title: "说明",
+        dataIndex: "description",
+      },
+    ];
+  }, []);
+
+  return (
+    <div className={styles.TopicSetting}>
+      <div className="ruleTop">
+        <div className="toprule">
+          <div className="pageTitle">
+            <div>助农课堂 题目设置</div>
+          </div>
+          <Button className="addTopicBtn" size="middle" type="primary">
+            新增
+          </Button>
+        </div>
+        {/* 表格主体 */}
+        <div className="tableBox1">
+          <Table
+            scroll={{ y: 625 }}
+            dataSource={results.list}
+            columns={columns}
+            rowKey="id"
+            pagination={{
+              showQuickJumper: true,
+              position: ["bottomCenter"],
+              showSizeChanger: true,
+              current: tableSelect.pageNum,
+              pageSize: tableSelect.pageSize,
+              total: results.total,
+              onChange: paginationChange,
+            }}
+          />
+        </div>
+        {/* 确认/取消按钮 */}
+        <div style={{marginTop: '10px'}}>
+          <Button type="primary" htmlType="submit">
+            提交
+          </Button>
+          &emsp;
+          <Popconfirm
+            title="放弃编辑后,信息将不会保存!"
+            okText="放弃"
+            cancelText="取消"
+            onConfirm={() => {
+              closeFu();
+            }}
+            okButtonProps={{ loading: false }}
+          >
+            <Button>取消</Button>
+          </Popconfirm>
+        </div>
+      </div>
+
+      {/* <Button className="scoreLimitBtn" size="middle" type="primary">
+        新增
+      </Button> */}
+    </div>
+  );
+}
+
+const MemoTopicSetting = React.memo(TopicSetting);
+
+export default MemoTopicSetting;

+ 87 - 3
houtai/src/pages/A1Rule/index.module.scss

@@ -1,5 +1,89 @@
-.AAAAA{
-  :global{
-    
+.A1Rule {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  background-color: rgb(239, 239, 239);
+
+  :global {
+    .ruleTop {
+      border-radius: 4px;
+      padding: 15px 20px 25px 20px;
+      background-color: #fff;
+      box-shadow: 3px 0px 10px 0px #d5d5d9;
+      position: relative;
+
+      .pageTitle {
+        .exportBtn {
+          width: 100px;
+          height: 40px;
+        }
+      }
+
+      .scoreLimitBtn {
+        position: absolute;
+        right: 2.5%;
+        top: 3%;
+        height: 30px;
+        padding: 0 10px;
+        background: #1F5CD8;
+        color: white;
+        border: 1px solid white;
+        border-radius: 5px;
+        cursor: pointer;
+        z-index: 10;
+        // transform: translateY(-50%);
+      }
+
+      .tableBox1 {
+        border-radius: 4px;
+        overflow: hidden;
+        margin-top: -10px;
+        // height: calc(100% - 80px);
+        // background-color: #fff;
+        padding: 0px;
+        // box-shadow: 3px 0px 10px 0px #d5d5d9;
+
+        .ant-table-body {
+          height: 300px;
+          overflow-y: auto !important;
+          overflow-y: overlay !important;
+
+          .ant-table-row {
+            .ant-table-cell {
+              padding: 10px;
+            }
+          }
+        }
+      }
+    }
+
+    .ruleBottom {
+      margin-top: 10px;
+
+      .tableBox2 {
+        border-radius: 4px;
+        overflow: hidden;
+        margin-top: -10px;
+        // height: calc(100% - 80px);
+        // background-color: #fff;
+        padding: 0px;
+        // box-shadow: 3px 0px 10px 0px #d5d5d9;
+
+        .ant-table-body {
+          height: 200px;
+          overflow-y: auto !important;
+          overflow-y: overlay !important;
+
+          .ant-table-row {
+            .ant-table-cell {
+              padding: 10px;
+            }
+          }
+        }
+      }
+    }
+
+
   }
 }

+ 283 - 10
houtai/src/pages/A1Rule/index.tsx

@@ -1,14 +1,287 @@
-import React from "react";
+import React, {
+  useCallback,
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+} from "react";
 import styles from "./index.module.scss";
- function AAAAA() {
-  
-  return (
-    <div className={styles.AAAAA}>
-      <h1>AAAAA</h1>
-    </div>
-  )
+import { Button, Form, Input, Modal, Popconfirm, Table } from "antd";
+import { useDispatch, useSelector } from "react-redux";
+import { RootState } from "@/store";
+import { RulesTableType, SaveScoreLimitType } from "@/types";
+import {
+  getRuleAPI,
+  getScoreLimitAPI,
+  scoreLimitSaveAPI,
+} from "@/store/action/A1Rule";
+import RuleEdit from "./RuleEdit";
+import TopicSetting from "./TopicSetting";
+import { MessageFu } from "@/utils/message";
+function A1Rule() {
+  const dispatch = useDispatch();
+
+  // 打开题目设置页面
+  const [topicSettingShow, setTopicSettingShow] = useState(false);
+
+  // 从仓库中获取表格数据
+  const tableInfo = useSelector((state: RootState) => state.A1Rule.tableInfo);
+
+  const [editPageShow, setEditPageShow] = useState(false);
+
+  const [surScoreLimit, setSurScoreLimit] = useState({} as any);
+
+  const getList = useCallback(async () => {
+    dispatch(getRuleAPI());
+    const res = await getScoreLimitAPI();
+    if (res.code === 0) {
+      setSurScoreLimit(res.data);
+    }
+  }, [dispatch]);
+
+  // 积分上限窗口开关
+  const [limitScoreShow, setLimitScoreShow] = useState(false);
+
+  // 编辑游戏
+  const editId = useRef(0);
+  // 编辑模式 1是游戏规则 2是线上展厅
+  const editMode = useRef(1);
+  const openEditPageFu = useCallback((type: number, id: number) => {
+    editMode.current = type;
+    editId.current = id;
+    setEditPageShow(true);
+  }, []);
+
+  const [form] = Form.useForm();
+
+  const onFinish = useCallback(
+    async (values: any) => {
+      if (values.numberVal) {
+        const res: any = await scoreLimitSaveAPI({} as SaveScoreLimitType);
+        if (res.code === 0) {
+          MessageFu.success("提交成功!");
+          getList();
+          setLimitScoreShow(false);
+        }
+      }
+    },
+    [getList]
+  );
+
+  const columns = useMemo(() => {
+    return [
+      {
+        title: "游戏名称",
+        dataIndex: "gameName",
+      },
+      {
+        title: "时限(秒)",
+        render: (item: RulesTableType) => {
+          return item.name === "乡村林场" ? <>-</> : <>60</>;
+        },
+      },
+      {
+        title: "得分",
+        dataIndex: "score",
+      },
+      {
+        title: "得分说明",
+        dataIndex: "specification",
+      },
+      {
+        title: "操作",
+        render: (item: RulesTableType) => {
+          return item.name === "助农课堂" ? (
+            <>
+              <Button
+                size="small"
+                type="text"
+                onClick={() => openEditPageFu(1, item.id!)}
+              >
+                编辑
+              </Button>
+              <Button
+                size="small"
+                type="text"
+                onClick={() => {
+                  setTopicSettingShow(true);
+                }}
+              >
+                设置题目
+              </Button>
+            </>
+          ) : (
+            <>
+              <Button
+                size="small"
+                type="text"
+                onClick={() => openEditPageFu(1, item.id!)}
+              >
+                编辑
+              </Button>
+            </>
+          );
+        },
+      },
+    ];
+  }, [openEditPageFu]);
+  const columns2 = useMemo(() => {
+    return [
+      {
+        title: "事件名称",
+        dataIndex: "eventName",
+      },
+      {
+        title: "得分",
+        dataIndex: "score",
+      },
+      {
+        title: "得分说明",
+        dataIndex: "specification",
+      },
+      {
+        title: "操作",
+        render: (item: RulesTableType) => {
+          return (
+            <>
+              <Button
+                size="small"
+                type="text"
+                onClick={() => openEditPageFu(2, item.id!)}
+              >
+                编辑
+              </Button>
+            </>
+          );
+        },
+      },
+    ];
+  }, [openEditPageFu]);
+
+  useEffect(() => {
+    dispatch(getRuleAPI());
+  }, [dispatch]);
+  return !topicSettingShow ? (
+    <>
+      <div className={styles.A1Rule}>
+        <div className="ruleTop">
+          <div className="pageTitle">游戏规则</div>
+          <button
+            className="scoreLimitBtn"
+            onClick={() => {
+              console.log("打开");
+              setLimitScoreShow(true);
+            }}
+          >
+            单日可获得积分上线:5000
+          </button>
+          {/* 表格主体 */}
+          <div className="tableBox1">
+            <Table
+              scroll={{ y: 500 }}
+              bordered={false}
+              dataSource={tableInfo.list}
+              columns={columns}
+              rowKey="id"
+              pagination={{
+                showQuickJumper: true,
+                position: ["bottomCenter"],
+                showSizeChanger: true,
+                total: tableInfo.total,
+              }}
+            />
+          </div>
+        </div>
+        <div className="ruleTop ruleBottom">
+          <div className="pageTitle">线上展厅</div>
+          {/* 表格主体 */}
+          <div className="tableBox2">
+            <Table
+              scroll={{ y: 500 }}
+              bordered={false}
+              dataSource={tableInfo.list}
+              columns={columns2}
+              rowKey="id"
+              pagination={{
+                showQuickJumper: true,
+                position: ["bottomCenter"],
+                showSizeChanger: true,
+                total: tableInfo.total,
+              }}
+            />
+          </div>
+        </div>
+        {/* 点击游戏编辑 */}
+        {editPageShow && editMode.current === 1 ? (
+          <RuleEdit
+            id={editId.current}
+            closePage={() => setEditPageShow(false)}
+            upTableList={getList}
+            editMode={editMode.current}
+          />
+        ) : null}
+        {/* 设置积分上线弹窗 */}
+        <Modal
+          destroyOnClose
+          closable={false}
+          maskClosable={false}
+          open={limitScoreShow}
+          title="   "
+          onCancel={() => setLimitScoreShow(false)}
+          footer={
+            [] // 设置footer为空,去掉 取消 确定默认按钮
+          }
+        >
+          <Form
+            form={form}
+            name="basic"
+            labelCol={{ span: 8 }}
+            onFinish={onFinish}
+            autoComplete="off"
+          >
+            <Form.Item
+              label="单日可获得积分上限"
+              name="numberVal"
+              style={{ marginTop: "40px" }}
+              rules={[{ required: true, message: "不能为空!" }]}
+              hide-required-asterisk={true}
+              getValueFromEvent={(e) =>
+                e.target.value.replace(/^(0+)|[^\d]+/g, "")
+              }
+            >
+              <Input
+                maxLength={9}
+                placeholder="请输入正整数,不超过999999999"
+              />
+            </Form.Item>
+            {/* 确定和取消按钮 */}
+            <br />
+            <Form.Item wrapperCol={{ offset: 9, span: 16 }}>
+              <Button type="primary" htmlType="submit">
+                提交
+              </Button>
+              &emsp;
+              <Popconfirm
+                title="放弃编辑后,信息将不会保存!"
+                okText="放弃"
+                cancelText="取消"
+                onConfirm={() => {
+                  setLimitScoreShow(false);
+                }}
+                okButtonProps={{ loading: false }}
+              >
+                <Button>取消</Button>
+              </Popconfirm>
+            </Form.Item>
+          </Form>
+        </Modal>
+      </div>
+    </>
+  ) : (
+    <TopicSetting closeFu={() => setTopicSettingShow(false)} />
+  );
 }
 
-const MemoAAAAA = React.memo(AAAAA);
+const MemoA1Rule = React.memo(A1Rule);
 
-export default MemoAAAAA;
+export default MemoA1Rule;

+ 25 - 28
houtai/src/pages/A2Integral/index.module.scss

@@ -1,37 +1,34 @@
-.A2Share {
-  width: 100%;
-  height: 100%;
-  display: flex;
-  flex-direction: column;
-  background-color: rgb(239, 239, 239);
+.A2Integral {
   :global {
-    .userTop {
-      border-radius: 4px;
-      padding: 15px 20px 25px 20px;
+    .logTop {
+      border-radius: 10px;
       background-color: #fff;
-      box-shadow: 3px 0px 10px 0px #d5d5d9;
-      .pageTitle {
-        .exportBtn {
-          width: 100px;
-          height: 40px;
-          
-        }
-      }
-      .flexRow {
+
+      .tableSelectBox {
+        padding: 15px 24px;
         display: flex;
-        justify-content: left;
         align-items: center;
-        margin-bottom: 20px;
-        .numberTxt {
-          margin-right: 10px;
+
+        .row {
+          margin-right: 20px;
+        }
+        .reSetBtn{
+          float: right;
+          height: 100%;
         }
       }
     }
-    .editFoot {
-      width: 100%;
-      margin-top: 20px;
-      display: flex;
-      justify-content: space-around;
+
+    .tableMain {
+      border-radius: 10px;
+      margin-top: 15px;
+      height: calc(100% - 75px);
+      background-color: #fff;
+
+      .ant-table-body {
+        height: 500px;
+
+      }
     }
   }
-}
+}

+ 152 - 380
houtai/src/pages/A2Integral/index.tsx

@@ -1,420 +1,192 @@
-import React, { useCallback, useEffect, useState } from "react";
-import styles from "./index.module.scss";
-import { Button, Form, Input, Modal, Popconfirm } from "antd";
-import { getShareAPI, shareEditAPI } from "@/store/action/A2Integral";
-import { useDispatch, useSelector } from "react-redux";
 import { RootState } from "@/store";
-import { MessageFu } from "@/utils/message";
+import { getLogListAPI } from "@/store/action/A7Log";
+import { Input, DatePicker, Table, Button, Select } from "antd";
+import React, { useEffect, useMemo, useRef, useState } from "react";
+import { useDispatch, useSelector } from "react-redux";
 
-import ExportJsonExcel from "js-export-excel";
-import html2canvas from "html2canvas";
+import styles from "./index.module.scss";
+import { IntegralTableAPIType } from "@/types";
 
-function A2Share() {
-  const dispatch = useDispatch();
-  const [open, setOpen] = useState(false);
-  const [exportOpen, setExportOpen] = useState(false);
+const { RangePicker } = DatePicker;
 
-  const shareInfo = useSelector((state: RootState) => state.A2Integral.shareInfo);
-  const [form] = Form.useForm();
-  const [curEdit, setCurEdit] = useState({} as any);
-  const onFinish = useCallback(
-    async (values: any) => {
-      if (values.numberVal) {
-        console.log(values.numberVal, curEdit, {
-          pcs: Number(values.numberVal),
-          sceneCode: "museum_cctv_mianyan",
-          type: curEdit.type,
-        });
-        const res: any = await shareEditAPI({
-          pcs: Number(values.numberVal),
-          sceneCode: "museum_cctv_mianyan",
-          type: curEdit.type,
-        });
-        if (res.code === 0) {
-          MessageFu.success("编辑成功!");
-          dispatch(getShareAPI());
-          setOpen(false);
-        }
-      }
-    },
-    [curEdit, dispatch]
-  );
+function A2Integral() {
+  const dispatch = useDispatch();
 
-  // 生成导出的数据行
-  const [editList, setEditList] = useState([
-    {
-      id: 1,
-      name: "用户浏览量",
-      numberVal: 2001,
-      type: "visit",
-      date: "",
-    },
-    {
-      id: 2,
-      name: "用户点赞量",
-      numberVal: 2002,
-      type: "star",
-      date: "",
-    },
-    {
-      id: 3,
-      name: "展区浏览量",
-      numberVal: 2003,
-      type: "area",
-      date: "",
-    },
-    {
-      id: 4,
-      name: "展位浏览量",
-      numberVal: 2004,
-      type: "booth",
-      date: "",
-    },
-    {
-      id: 5,
-      name: "展品浏览量",
-      numberVal: 2004,
-      type: "exhibits",
-      date: "",
-    },
-  ]);
+  const pageNumRef = useRef(1);
+  const pagePageRef = useRef(10);
+  // 筛选和分页
+  const [tableSelect, setTableSelect] = useState({
+    searchKey: "",
+    pageSize: 10,
+    pageNum: 1,
+    startTime: "",
+    endTime: "",
+    type: "",
+  });
 
-  // 导出excel
-  const exportExcel = useCallback(() => {
-    let sheetFilter = ["id", "name", "numberVal", "date"];
-    let option = {} as any;
-    option.fileName = `云展数据统计`;
-    option.datas = [
-      {
-        sheetData: editList,
-        sheetName: `云展数据统计`,
-        sheetFilter: sheetFilter,
-        sheetHeader: ["序号", "标题", "数量", "日期"],
-        columnWidths: [10, 10, 10, 10],
-      },
-    ];
-    var toExcel = new ExportJsonExcel(option); //new
-    toExcel.saveExcel(); //保存
-    setExportOpen(false);
-  }, [editList]);
+  // 账号的输入
+  const nameTime = useRef(-1);
+  const nameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+    clearTimeout(nameTime.current);
+    nameTime.current = window.setTimeout(() => {
+      setTableSelect({ ...tableSelect, searchKey: e.target.value, pageNum: 1 });
+    }, 500);
+  };
+  // 时间选择器改变
+  const timeChange = (date: any, dateString: any) => {
+    let startTime = "";
+    let endTime = "";
+    if (dateString[0] && dateString[1]) {
+      startTime = dateString[0] + " 00:00:00";
+      endTime = dateString[1] + " 23:59:59";
+    }
+    setTableSelect({ ...tableSelect, startTime, endTime, pageNum: 1 });
+  };
 
-  // 点击下载海报
-  const [donImg, setDonImg] = useState(false);
+  // 类型选择发生改变
+  const typeChange = (value: any) => {
+    setTableSelect({ ...tableSelect, type: value, pageNum: 1 });
+  };
 
-  const dataURLToBlob = useCallback((dataurl: any) => {
-    let arr = dataurl.split(",");
-    let mime = arr[0].match(/:(.*?);/)[1];
-    let bstr = atob(arr[1]);
-    let n = bstr.length;
-    let u8arr = new Uint8Array(n);
-    while (n--) {
-      u8arr[n] = bstr.charCodeAt(n);
-    }
-    return new Blob([u8arr], { type: mime });
-  }, []);
+  const [inputKey, setInputKey] = useState(1);
+  // 重置
+  const resetFu = () => {
+    setInputKey(Date.now());
+    setTableSelect({
+      searchKey: "",
+      pageSize: 10,
+      pageNum: 1,
+      startTime: "",
+      endTime: "",
+      type: "",
+    });
+  };
 
-  // 导出截图
-  const exportPNG = useCallback(() => {
-    setDonImg(true);
-    window.setTimeout(() => {
-      const canEle: HTMLDivElement = document.querySelector(".H5MainBoxInfo")!; //获取dom
-      let a = document.createElement("a");
-      html2canvas(canEle, {
-        backgroundColor: "transparent",
-        allowTaint: true,
-        useCORS: true,
-      }).then((canvas) => {
-        let dom = document.body.appendChild(canvas);
-        dom.style.display = "none";
-        a.style.display = "none";
-        document.body.removeChild(dom);
-        let blob: any = dataURLToBlob(dom.toDataURL("image/png"));
-        a.setAttribute("href", URL.createObjectURL(blob));
-        //这块是保存图片操作  可以设置保存的图片的信息
-        a.setAttribute("download", "云展览数据.png");
-        document.body.appendChild(a);
-        a.click();
-        URL.revokeObjectURL(blob);
-        document.body.removeChild(a);
-        setDonImg(false);
-        setExportOpen(false);
-      });
-    }, 100);
-  }, [dataURLToBlob]);
+  useEffect(() => {
+    pageNumRef.current = tableSelect.pageNum;
+    pagePageRef.current = tableSelect.pageSize;
+    dispatch(getLogListAPI(tableSelect));
+  }, [dispatch, tableSelect]);
 
-  // 回显
-  const getInfoFu = useCallback(
-    (v: any) => {
-      setCurEdit(v);
-      const { numberVal } = v;
-      form.setFieldsValue({
-        numberVal: numberVal,
-      });
-      console.log(curEdit);
-    },
-    [curEdit, form]
-  );
+  // ---------关于表格
 
-  const onFinishFailed = (errorInfo: any) => {
-    console.log("Failed:", errorInfo);
+  // 页码变化
+  const paginationChange = (pageNum: number, pageSize: number) => {
+    pageNumRef.current = pageNum;
+    pagePageRef.current = pageSize;
+    setTableSelect({ ...tableSelect, pageNum, pageSize });
   };
 
-  useEffect(() => {
-    dispatch(getShareAPI());
-  }, [dispatch]);
+  const results = useSelector((state: RootState) => state.A7Log.tableInfo);
 
-  useEffect(() => {
-    let date = new Date().toLocaleDateString("zh-CN");
-    setEditList([
+  const columns = useMemo(() => {
+    return [
+      // {
+      //   width: 100,
+      //   title: "序号",
+      //   render: (text: any, record: any, index: any) =>
+      //     index + 1 + (pageNumRef.current - 1) * pagePageRef.current,
+      // },
       {
-        id: 1,
-        name: "用户浏览量",
-        numberVal: shareInfo.pcsVisitShow,
-        type: "visit",
-        date: date,
+        title: "用户名",
+        dataIndex: "userName",
       },
       {
-        id: 2,
-        name: "用户点赞量",
-        numberVal: shareInfo.pcsStarShow,
-        type: "star",
-        date: date,
+        title: "时间",
+        dataIndex: "createTime",
       },
       {
-        id: 3,
-        name: "展区浏览量",
-        numberVal: shareInfo.pcsArea,
-        type: "area",
-        date: date,
+        title: "类型",
+        dataIndex: "ip",
       },
       {
-        id: 4,
-        name: "展位浏览量",
-        numberVal: shareInfo.pcsBooth,
-        type: "booth",
-        date: date,
+        title: "积分",
+        dataIndex: "type",
       },
       {
-        id: 5,
-        name: "展品浏览量",
-        numberVal: shareInfo.pcsExhibits,
-        type: "exhibits",
-        date: date,
+        title: "说明",
+        render: (item: IntegralTableAPIType) => {
+          return (
+            <>
+            {item.explain}
+            </>
+          );
+        },
       },
-    ]);
-  }, [shareInfo]);
+    ];
+  }, []);
 
   return (
-    <div className={styles.A2Share}>
-      <div className="H5MainBoxInfo">
-        <div className="userTop">
-          <div className="pageTitle">
-            数据管理
-            {!donImg ? (
-              <div
-                style={{
-                  display: "flex",
-                  flexDirection: "column",
-                  float: "right",
-                  justifyContent: "center",
-                  alignItems: "center",
-                }}
-              >
-                <Button
-                  type="primary"
-                  style={{
-                    width: "70px",
-                    height: "30px",
-                    borderRadius: "3px",
-                    boxShadow: "none",
-                    fontSize: "12px",
-                    float: "right",
-                  }}
-                  onClick={() => {
-                    setExportOpen(true);
-                  }}
-                >
-                  导出
-                </Button>
-                <div
-                  style={{
-                    fontSize: "12px",
-                    color: "gray",
-                    float: "right",
-                    marginTop: "5px",
-                  }}
-                >
-                  导出excel,png文件
-                </div>
-              </div>
-            ) : (
-              ""
-            )}
-            <div
-              style={{
-                color: "gray",
-                fontSize: "15px",
-                float: "right",
-                marginRight: "40px",
-              }}
-            >
-              <span style={{ marginRight: "20px" }}>
-                真实浏览量:{shareInfo.pcsVisit}
-              </span>
-              <span>真实点赞量:{shareInfo.pcsStar}</span>
-            </div>
+    <div className={styles.A2Integral}>
+      <div className="pageTitle">积分记录</div>
+      <div className="logTop">
+        <div className="tableSelectBox">
+          <div className="row">
+            <span>用户名:</span>
+            <Input
+              key={inputKey}
+              maxLength={15}
+              style={{ width: 150 }}
+              placeholder="请输入"
+              allowClear
+              onChange={(e) => nameChange(e)}
+            />
           </div>
-          {editList.map((v) => (
-            <div className="flexRow" key={v.id}>
-              <div className="numberTxt">
-                {v.name}:&emsp;{v.numberVal ? v.numberVal : 0}
-              </div>
-              <Button
-                type="primary"
-                style={{
-                  width: "70px",
-                  height: "30px",
-                  borderRadius: "3px",
-                  boxShadow: "none",
-                  fontSize: "12px",
-                }}
-                onClick={() => {
-                  getInfoFu(v);
-                  setOpen(true);
-                }}
-              >
-                修改
-              </Button>
-            </div>
-          ))}
-        </div>
-      </div>
-      {/* 点击修改按钮后的修改弹窗 */}
-      <Modal
-        destroyOnClose
-        closable={false}
-        maskClosable={false}
-        open={open}
-        title="   "
-        onCancel={() => setOpen(false)}
-        footer={
-          [] // 设置footer为空,去掉 取消 确定默认按钮
-        }
-      >
-        <Form
-          form={form}
-          name="basic"
-          labelCol={{ span: 5 }}
-          onFinish={onFinish}
-          onFinishFailed={onFinishFailed}
-          autoComplete="off"
-        >
-          <Form.Item
-            label={curEdit.name}
-            name="numberVal"
-            style={{ marginTop: "40px" }}
-            rules={[{ required: true, message: "不能为空!" }]}
-            hide-required-asterisk={true}
-            getValueFromEvent={(e) =>
-              e.target.value.replace(/^(0+)|[^\d]+/g, "")
-            }
-          >
-            <Input maxLength={9} placeholder="请输入正整数,不超过999999999" />
-          </Form.Item>
-          {/* 确定和取消按钮 */}
-          <br />
-          <Form.Item wrapperCol={{ offset: 9, span: 16 }}>
-            <Button type="primary" htmlType="submit">
-              提交
-            </Button>
-            &emsp;
-            <Popconfirm
-              title="放弃编辑后,信息将不会保存!"
-              okText="放弃"
-              cancelText="取消"
-              onConfirm={() => {
-                setOpen(false);
-              }}
-              okButtonProps={{ loading: false }}
-            >
-              <Button>取消</Button>
-            </Popconfirm>
-          </Form.Item>
-        </Form>
-      </Modal>
-      {/* 点击导出,选择导出格式 */}
-      <Modal
-        destroyOnClose
-        closable={false}
-        maskClosable={false}
-        open={exportOpen}
-        title="选择需要导出的格式"
-        onCancel={() => setExportOpen(false)}
-        footer={
-          [] // 设置footer为空,去掉 取消 确定默认按钮
-        }
-      >
-        <div
-          style={{
-            width: "100%",
-            display: "flex",
-            justifyContent: "space-around",
-            marginTop: "30px",
-            marginBottom: "30px",
-          }}
-        >
-          <Button
-            type="primary"
-            onClick={() => {
-              exportExcel();
-            }}
-          >
-            Excle
-          </Button>
+          <div className="row">
+            <span>日期:</span>
+            <RangePicker key={inputKey} onChange={timeChange} />
+          </div>
+
+          <div className="row">
+            <span>类型:</span>
+            <Select
+              value={tableSelect.type}
+              defaultValue="lucy"
+              style={{ width: 120 }}
+              onChange={typeChange}
+              options={[
+                { value: "jack", label: "Jack" },
+                { value: "lucy", label: "Lucy" },
+                { value: "Yiminghe", label: "yiminghe" },
+              ]}
+            />
+          </div>
+
           <Button
+            className="reSetBtn"
+            size="small"
             type="primary"
             onClick={() => {
-              exportPNG();
+              resetFu();
             }}
           >
-            png
+            重置
           </Button>
-          {/* <Button
-            type="primary"
-            onClick={() => {
-              exportWord();
-            }}
-          >
-            Word
-          </Button> */}
         </div>
-        <div
-          style={{
-            width: "100%",
-            display: "flex",
-            justifyContent: "end",
+      </div>
+
+      {/* 表格主体 */}
+      <div className="tableMain">
+        <Table
+          scroll={{ y: 625 }}
+          dataSource={results.list}
+          columns={columns}
+          rowKey="id"
+          pagination={{
+            showQuickJumper: true,
+            position: ["bottomCenter"],
+            showSizeChanger: true,
+            current: tableSelect.pageNum,
+            pageSize: tableSelect.pageSize,
+            total: results.total,
+            onChange: paginationChange,
           }}
-        >
-          <Popconfirm
-            title="放弃编辑后,信息将不会保存!"
-            okText="放弃"
-            cancelText="取消"
-            onConfirm={() => {
-              setExportOpen(false);
-            }}
-            style={{
-              float: "right",
-            }}
-            okButtonProps={{ loading: false }}
-          >
-            <Button>取消</Button>
-          </Popconfirm>
-        </div>
-      </Modal>
+        />
+      </div>
     </div>
   );
 }
 
-const MemoA2Share = React.memo(A2Share);
+const MemoA2Integral = React.memo(A2Integral);
 
-export default MemoA2Share;
+export default MemoA2Integral;

+ 53 - 3
houtai/src/pages/A4Prize/index.module.scss

@@ -1,5 +1,55 @@
-.AAAAA{
-  :global{
-    
+.A4Prize {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  background-color: rgb(239, 239, 239);
+
+  :global {
+    .ruleTop {
+      border-radius: 4px;
+      padding: 15px 20px 25px 20px;
+      background-color: #fff;
+      box-shadow: 3px 0px 10px 0px #d5d5d9;
+      position: relative;
+
+      .pageTitle {
+        .exportBtn {
+          width: 100px;
+          height: 40px;
+        }
+      }
+
+      .scoreLimitBtn {
+        position: absolute;
+        right: 2.5%;
+        top: 3%;
+        height: 30px;
+        cursor: pointer;
+        // transform: translateY(-50%);
+      }
+
+      .tableBox1 {
+        border-radius: 4px;
+        overflow: hidden;
+        margin-top: -10px;
+        // height: calc(100% - 80px);
+        // background-color: #fff;
+        padding: 0px;
+        // box-shadow: 3px 0px 10px 0px #d5d5d9;
+
+        .ant-table-body {
+          height: 300px;
+          overflow-y: auto !important;
+          overflow-y: overlay !important;
+
+          .ant-table-row {
+            .ant-table-cell {
+              padding: 10px;
+            }
+          }
+        }
+      }
+    }
   }
 }

+ 380 - 8
houtai/src/pages/A4Prize/index.tsx

@@ -1,14 +1,386 @@
-import React from "react";
+import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
 import styles from "./index.module.scss";
- function AAAAA() {
-  
+import {
+  Button,
+  Form,
+  Input,
+  Modal,
+  Table,
+  Popconfirm,
+  DatePicker,
+  DatePickerProps,
+  Select,
+  Upload,
+  message,
+} from "antd";
+import { useDispatch, useSelector } from "react-redux";
+import { RootState } from "@/store";
+import { AddPrizeType, PrizeTableType } from "@/types";
+import ImageLazy from "@/components/ImageLazy";
+import {
+  addPrizeByIdAPI,
+  deletePrizeByIdAPI,
+  editPrizeByIdAPI,
+  getPrizeDetailAPI,
+  getPrizeListAPI,
+} from "@/store/action/A4Prise";
+import { MessageFu } from "@/utils/message";
+import { RangePickerProps } from "antd/es/date-picker";
+import { LoadingOutlined, PlusOutlined } from "@ant-design/icons";
+import {
+  RcFile,
+  UploadChangeParam,
+  UploadFile,
+  UploadProps,
+} from "antd/es/upload";
+import RichText from "@/components/Z_RichText";
+
+function A4Prize() {
+  const dispatch = useDispatch();
+  // 从仓库中获取表格数据
+  const tableInfo = useSelector((state: RootState) => state.A4Prise.tableInfo);
+
+  // 当前是编辑还是增加?
+  const [modalType, setModalType] = React.useState<string>("add");
+
+  // 当前编辑单元
+  const [editItem, setEditItem] = React.useState<PrizeTableType>();
+  // 编辑/新增页面弹窗开关
+  const [editPageVisible, setEditPageVisible] = React.useState(false);
+  // 编辑/新增页面弹窗打开
+  const openEditPageFu = useCallback(
+    async (id?: number) => {
+      setEditPageVisible(true);
+      if (id) {
+        setModalType("edit");
+        // 获取奖品详情
+        const res = await getPrizeDetailAPI(id);
+        if (res.code === 0) {
+          setEditItem(res.data);
+        }
+      } else {
+        setModalType("add");
+      }
+    },
+    [setEditItem]
+  );
+
+  // 通过id删除奖品
+  const deletePrizeFu = useCallback(async (id: number) => {
+    const res = await deletePrizeByIdAPI(id);
+    if (res.code === 0) {
+      MessageFu.success("删除成功");
+    }
+  }, []);
+  const [form] = Form.useForm();
+
+  const getList = useCallback(async () => {
+    dispatch(getPrizeListAPI());
+  }, [dispatch]);
+
+  const onFinish = useCallback(
+    async (values: any) => {
+      if (values.numberVal) {
+        const res: any =
+          modalType === "add"
+            ? await addPrizeByIdAPI({} as AddPrizeType)
+            : await editPrizeByIdAPI({} as AddPrizeType);
+        if (res.code === 0) {
+          MessageFu.success("提交成功!");
+          getList();
+          setEditPageVisible(false);
+        }
+      }
+    },
+    [getList, modalType]
+  );
+
+  const [loading, setLoading] = React.useState<boolean>(false);
+
+  const [imageUrl, setImageUrl] = React.useState<string>("");
+
+  const getBase64 = (img: RcFile, callback: (url: string) => void) => {
+    const reader = new FileReader();
+    reader.addEventListener("load", () => callback(reader.result as string));
+    reader.readAsDataURL(img);
+  };
+
+  const handleChange = (value: string) => {
+    console.log(`selected ${value}`);
+  };
+
+  const handleUploadChange: UploadProps["onChange"] = (
+    info: UploadChangeParam<UploadFile>
+  ) => {
+    if (info.file.status === "uploading") {
+      setLoading(true);
+      return;
+    }
+    if (info.file.status === "done") {
+      // Get this url from response in real world.
+      getBase64(info.file.originFileObj as RcFile, (url) => {
+        setLoading(false);
+        setImageUrl(url);
+      });
+    }
+  };
+
+  useEffect(() => {
+    getList();
+  }, [dispatch, getList]);
+  const columns = useMemo(() => {
+    return [
+      {
+        title: "奖品名称",
+        dataIndex: "name",
+      },
+      {
+        title: "封面",
+        render: (item: PrizeTableType) => (
+          <div className="tableImgAuto">
+            <ImageLazy width={60} height={60} src={item.thumb!} />
+          </div>
+        ),
+      },
+      {
+        title: "所需积分",
+        dataIndex: "needScore",
+      },
+      {
+        title: "库存",
+        dataIndex: "inventory",
+      },
+      {
+        title: "登记日期",
+        dataIndex: "date",
+      },
+      {
+        title: "状态",
+        dataIndex: "state",
+      },
+      {
+        title: "操作",
+        render: (item: PrizeTableType) => {
+          return (
+            <>
+              <Button
+                size="small"
+                type="text"
+                onClick={() => openEditPageFu(item.id)}
+              >
+                编辑
+              </Button>
+              <Button
+                size="small"
+                type="text"
+                onClick={() => deletePrizeFu(item.id)}
+              >
+                删除
+              </Button>
+            </>
+          );
+        },
+      },
+    ];
+  }, [deletePrizeFu, openEditPageFu]);
+
+  const onChange = (
+    value: DatePickerProps["value"] | RangePickerProps["value"],
+    dateString: [string, string] | string
+  ) => {
+    console.log("Selected Time: ", value);
+    console.log("Formatted Selected Time: ", dateString);
+  };
+
+  const onOk = (
+    value: DatePickerProps["value"] | RangePickerProps["value"]
+  ) => {
+    console.log("onOk: ", value);
+  };
+
+  const beforeUpload = (file: RcFile) => {
+    const isJpgOrPng = file.type === "image/jpeg" || file.type === "image/png";
+    if (!isJpgOrPng) {
+      message.error("You can only upload JPG/PNG file!");
+    }
+    const isLt2M = file.size / 1024 / 1024 < 2;
+    if (!isLt2M) {
+      message.error("Image must smaller than 2MB!");
+    }
+    return isJpgOrPng && isLt2M;
+  };
+
+  const uploadButton = (
+    <div>
+      {loading ? <LoadingOutlined /> : <PlusOutlined />}
+      <div style={{ marginTop: 8 }}>Upload</div>
+    </div>
+  );
+
+  // 富文本的ref
+  const richTxtRef = useRef<any>(null);
+
+  // 文件的校验
+  const [check, setCheck] = useState(false);
+
+  // 文件的code码
+  const [dirCode, setDirCode] = useState("");
+
   return (
-    <div className={styles.AAAAA}>
-      <h1>AAAAA</h1>
+    <div className={styles.A4Prize}>
+      <div className="ruleTop">
+        <div className="pageTitle">奖品管理</div>
+        <Button
+          className="scoreLimitBtn"
+          size="small"
+          type="primary"
+          onClick={() => setEditPageVisible(true)}
+        >
+          新增
+        </Button>
+
+        {/* 表格主体 */}
+        <div className="tableBox1">
+          <Table
+            scroll={{ y: 500 }}
+            bordered={false}
+            dataSource={tableInfo.list}
+            columns={columns}
+            rowKey="id"
+            pagination={{
+              showQuickJumper: true,
+              position: ["bottomCenter"],
+              showSizeChanger: true,
+              total: tableInfo.total,
+            }}
+          />
+        </div>
+      </div>
+      {/* 编辑/新增弹窗 */}
+      <Modal
+        destroyOnClose
+        closable={false}
+        maskClosable={false}
+        open={editPageVisible}
+        title={modalType === "add" ? "新增奖品" : "编辑奖品"}
+        width={1000}
+        onCancel={() => setEditPageVisible(false)}
+        footer={
+          [] // 设置footer为空,去掉 取消 确定默认按钮
+        }
+      >
+        <Form
+          form={form}
+          name="basic"
+          labelCol={{ span: 3 }}
+          onFinish={onFinish}
+          autoComplete="off"
+        >
+          <Form.Item
+            label="奖品名称"
+            name="name"
+            rules={[{ required: true, message: "不能为空!" }]}
+          >
+            <Input maxLength={20} placeholder="请输入内容,不超过20个字" />
+          </Form.Item>
+          <Form.Item
+            label="所需的积分"
+            name="needScore"
+            rules={[{ required: true, message: "不能为空!" }]}
+          >
+            <Input maxLength={5} placeholder="请输入正整数,1-99999" />
+          </Form.Item>
+          <Form.Item
+            label="库存"
+            name="inventory"
+            rules={[{ required: true, message: "不能为空!" }]}
+          >
+            <Input maxLength={5} placeholder="请输入正整数,1-99999" />
+          </Form.Item>
+          <Form.Item
+            label="登记日期"
+            name="date"
+            rules={[{ required: true, message: "不能为空!" }]}
+          >
+            <DatePicker showTime onChange={onChange} onOk={onOk} />
+          </Form.Item>
+          <Form.Item
+            label="状态"
+            name="state"
+            rules={[{ required: true, message: "不能为空!" }]}
+          >
+            <Select
+              defaultValue="上架"
+              style={{ width: 120 }}
+              onChange={handleChange}
+              options={[
+                { value: "上架", label: "上架" },
+                { value: "下架", label: "下架" },
+              ]}
+            />
+          </Form.Item>
+          <Form.Item
+            label="封面"
+            name="themb"
+            rules={[{ required: true, message: "不能为空!" }]}
+          >
+            <Upload
+              name="avatar"
+              listType="picture-card"
+              className="avatar-uploader"
+              showUploadList={false}
+              action="https://run.mocky.io/v3/435e224c-44fb-4773-9faf-380c5e6a2188"
+              beforeUpload={beforeUpload}
+              onChange={handleUploadChange}
+            >
+              {imageUrl ? (
+                <img src={imageUrl} alt="avatar" style={{ width: "100%" }} />
+              ) : (
+                uploadButton
+              )}
+            </Upload>
+            <span>
+              格式要求:支持png、jpg和jpeg的图片格式;最大支持2M;最多1张
+            </span>
+          </Form.Item>
+          <Form.Item
+            label="产品简介"
+            name="introduction"
+            rules={[{ required: true, message: "不能为空!" }]}
+          >
+            <RichText
+              myUrl="cms/goods/upload"
+              ref={richTxtRef}
+              check={check}
+              dirCode={dirCode}
+              isLook={true}
+            />
+          </Form.Item>
+          {/* 确定和取消按钮 */}
+          <br />
+          <Form.Item wrapperCol={{ offset: 9, span: 16 }}>
+            <Button type="primary" htmlType="submit">
+              提交
+            </Button>
+            &emsp;
+            <Popconfirm
+              title="放弃编辑后,信息将不会保存!"
+              okText="放弃"
+              cancelText="取消"
+              onConfirm={() => {
+                setEditPageVisible(false);
+              }}
+              okButtonProps={{ loading: false }}
+            >
+              <Button>取消</Button>
+            </Popconfirm>
+          </Form.Item>
+        </Form>
+      </Modal>
     </div>
-  )
+  );
 }
 
-const MemoAAAAA = React.memo(AAAAA);
+const MemoA4Prize = React.memo(A4Prize);
 
-export default MemoAAAAA;
+export default MemoA4Prize;

+ 32 - 3
houtai/src/pages/A5Exchange/index.module.scss

@@ -1,5 +1,34 @@
-.AAAAA{
-  :global{
-    
+.A5Exchange {
+  :global {
+    .logTop {
+      border-radius: 10px;
+      background-color: #fff;
+
+      .tableSelectBox {
+        padding: 15px 24px;
+        display: flex;
+        align-items: center;
+
+        .row {
+          margin-right: 20px;
+        }
+        .reSetBtn{
+          float: right;
+          height: 100%;
+        }
+      }
+    }
+
+    .tableMain {
+      border-radius: 10px;
+      margin-top: 15px;
+      height: calc(100% - 75px);
+      background-color: #fff;
+
+      .ant-table-body {
+        height: 500px;
+
+      }
+    }
   }
 }

+ 164 - 8
houtai/src/pages/A5Exchange/index.tsx

@@ -1,14 +1,170 @@
-import React from "react";
+import { RootState } from "@/store";
+import { getLogListAPI } from "@/store/action/A7Log";
+import { Input, DatePicker, Table, Button } from "antd";
+import React, { useEffect, useMemo, useRef, useState } from "react";
+import { useDispatch, useSelector } from "react-redux";
+
 import styles from "./index.module.scss";
- function AAAAA() {
-  
+
+const { RangePicker } = DatePicker;
+
+function A5Exchange() {
+  const dispatch = useDispatch();
+
+  const pageNumRef = useRef(1);
+  const pagePageRef = useRef(10);
+  // 筛选和分页
+  const [tableSelect, setTableSelect] = useState({
+    searchKey: "",
+    pageSize: 10,
+    pageNum: 1,
+    startTime: "",
+    endTime: "",
+  });
+
+  // 账号的输入
+  const nameTime = useRef(-1);
+  const nameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+    clearTimeout(nameTime.current);
+    nameTime.current = window.setTimeout(() => {
+      setTableSelect({ ...tableSelect, searchKey: e.target.value, pageNum: 1 });
+    }, 500);
+  };
+  // 时间选择器改变
+  const timeChange = (date: any, dateString: any) => {
+    let startTime = "";
+    let endTime = "";
+    if (dateString[0] && dateString[1]) {
+      startTime = dateString[0] + " 00:00:00";
+      endTime = dateString[1] + " 23:59:59";
+    }
+    setTableSelect({ ...tableSelect, startTime, endTime, pageNum: 1 });
+  };
+
+  const [inputKey, setInputKey] = useState(1);
+  // 重置
+  const resetFu = () => {
+    setInputKey(Date.now());
+    setTableSelect({
+      searchKey: "",
+      pageSize: 10,
+      pageNum: 1,
+      startTime: "",
+      endTime: "",
+    });
+  };
+
+  useEffect(() => {
+    pageNumRef.current = tableSelect.pageNum;
+    pagePageRef.current = tableSelect.pageSize;
+    dispatch(getLogListAPI(tableSelect));
+  }, [dispatch, tableSelect]);
+
+  // ---------关于表格
+
+  // 页码变化
+  const paginationChange = (pageNum: number, pageSize: number) => {
+    pageNumRef.current = pageNum;
+    pagePageRef.current = pageSize;
+    setTableSelect({ ...tableSelect, pageNum, pageSize });
+  };
+
+  const results = useSelector((state: RootState) => state.A7Log.tableInfo);
+
+  const columns = useMemo(() => {
+    return [
+      // {
+      //   width: 100,
+      //   title: "序号",
+      //   render: (text: any, record: any, index: any) =>
+      //     index + 1 + (pageNumRef.current - 1) * pagePageRef.current,
+      // },
+      {
+        title: "用户名",
+        dataIndex: "userName",
+      },
+      {
+        title: "兑换日期",
+        dataIndex: "createTime",
+      },
+      {
+        title: "兑换奖品",
+        dataIndex: "ip",
+      },
+      {
+        title: "积分记录",
+        dataIndex: "type",
+      },
+      {
+        title: "称呼",
+        dataIndex: "description",
+      },
+      {
+        title: "联系方式",
+        dataIndex: "description",
+      },
+      {
+        title: "地址和留言",
+        dataIndex: "description",
+      },
+    ];
+  }, []);
+
   return (
-    <div className={styles.AAAAA}>
-      <h1>AAAAA</h1>
+    <div className={styles.A5Exchange}>
+      <div className="pageTitle">兑换记录</div>
+      <div className="logTop">
+        <div className="tableSelectBox">
+          <div className="row">
+            <span>用户名:</span>
+            <Input
+              key={inputKey}
+              maxLength={15}
+              style={{ width: 150 }}
+              placeholder="请输入"
+              allowClear
+              onChange={(e) => nameChange(e)}
+            />
+          </div>
+          <div className="row">
+            <span>日期:</span>
+            <RangePicker key={inputKey} onChange={timeChange} />
+          </div>
+          <Button
+            className="reSetBtn"
+            size="small"
+            type="primary"
+            onClick={() => {
+              resetFu();
+            }}
+          >
+            重置
+          </Button>
+        </div>
+      </div>
+
+      {/* 表格主体 */}
+      <div className="tableMain">
+        <Table
+          scroll={{ y: 625 }}
+          dataSource={results.list}
+          columns={columns}
+          rowKey="id"
+          pagination={{
+            showQuickJumper: true,
+            position: ["bottomCenter"],
+            showSizeChanger: true,
+            current: tableSelect.pageNum,
+            pageSize: tableSelect.pageSize,
+            total: results.total,
+            onChange: paginationChange,
+          }}
+        />
+      </div>
     </div>
-  )
+  );
 }
 
-const MemoAAAAA = React.memo(AAAAA);
+const MemoA5Exchange = React.memo(A5Exchange);
 
-export default MemoAAAAA;
+export default MemoA5Exchange;

+ 34 - 0
houtai/src/pages/A6IDUser/IntegralEdit/index.module.scss

@@ -0,0 +1,34 @@
+.IntegralEdit {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  background-color: rgb(239, 239, 239);
+
+  :global {
+    .pageTitle {
+      font-size: 25px;
+      display: flex;
+      justify-content: space-between;
+      
+      &:nth-child(2) {
+        margin-left: 10px;
+      }
+    }
+
+    .pageTitle::before {
+      background: none;
+    }
+
+    .tableMain {
+      border-radius: 10px;
+      height: calc(100%);
+      background-color: #fff;
+
+      .ant-table-body {
+        height: 500px;
+
+      }
+    }
+  }
+}

+ 221 - 0
houtai/src/pages/A6IDUser/IntegralEdit/index.tsx

@@ -0,0 +1,221 @@
+import { RootState } from "@/store";
+import { Button, Form, Input, Modal, Popconfirm, Table } from "antd";
+import React, {
+  useCallback,
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+} from "react";
+import { useDispatch, useSelector } from "react-redux";
+
+import styles from "./index.module.scss";
+import {
+  IDUserScoreSaveAPI,
+  getIDUserInfoByIdAPI,
+} from "@/store/action/A6IDUser";
+import { IDUserType, SaveIDUserScoreType } from "@/types";
+import { MessageFu } from "@/utils/message";
+type Props = {
+  id: number; //用户id
+  closeFu: () => void;
+};
+
+function IntegralEdit({ id,closeFu }: Props) {
+  const dispatch = useDispatch();
+
+  const pageNumRef = useRef(1);
+  const pagePageRef = useRef(10);
+  // 筛选和分页
+  const [tableSelect, setTableSelect] = useState({
+    searchKey: "",
+    pageSize: 10,
+    pageNum: 1,
+    startTime: "",
+    endTime: "",
+  });
+
+  // 获取当前用户信息
+  const [curIDUser, setCurIDUser] = useState<IDUserType>({
+    id: 1,
+    name: "用户1",
+  } as IDUserType);
+
+  const getInfoById = useCallback(async () => {
+    const res = await getIDUserInfoByIdAPI(id);
+    if (res.code === 0) {
+      setCurIDUser(res.data);
+    }
+  }, [id]);
+
+  useEffect(() => {
+    pageNumRef.current = tableSelect.pageNum;
+    pagePageRef.current = tableSelect.pageSize;
+    getInfoById();
+  }, [dispatch, getInfoById, tableSelect]);
+
+  // ---------关于表格
+
+  // 页码变化
+  const paginationChange = (pageNum: number, pageSize: number) => {
+    pageNumRef.current = pageNum;
+    pagePageRef.current = pageSize;
+    setTableSelect({ ...tableSelect, pageNum, pageSize });
+  };
+
+  const results = useSelector((state: RootState) => state.A7Log.tableInfo);
+
+  const columns = useMemo(() => {
+    return [
+      {
+        title: "时间",
+        dataIndex: "createTime",
+      },
+      {
+        title: "类型",
+        dataIndex: "type",
+      },
+      {
+        title: "积分",
+        dataIndex: "type",
+      },
+      {
+        title: "说明",
+        dataIndex: "description",
+      },
+    ];
+  }, []);
+
+  // 修改积分弹窗开关
+  const [editIntegralVisible, setEditIntegralVisible] = useState(false);
+  const [form] = Form.useForm();
+
+  const onFinish = useCallback(
+    async (values: any) => {
+      if (values.numberVal) {
+        const res: any = await IDUserScoreSaveAPI({} as SaveIDUserScoreType);
+        if (res.code === 0) {
+          MessageFu.success("提交成功!");
+          pageNumRef.current = tableSelect.pageNum;
+          pagePageRef.current = tableSelect.pageSize;
+          getInfoById();
+          setEditIntegralVisible(false);
+        }
+      }
+    },
+    [getInfoById, tableSelect.pageNum, tableSelect.pageSize]
+  );
+
+  return (
+    <div className={styles.IntegralEdit}>
+      <div className="pageTitle">
+        <div>{curIDUser.name}</div>
+        <div>当前积分:5000</div>
+        <div>
+          <Button
+            className="scoreLimitBtn"
+            size="middle"
+            type="primary"
+            onClick={() => setEditIntegralVisible(true)}
+          >
+            修改积分
+          </Button>
+          <Button
+            className="scoreLimitBtn"
+            size="middle"
+            type="primary"
+            style={{ marginLeft: "10px" }}
+            onClick={() => closeFu()}
+          >
+            返回
+          </Button>
+        </div>
+      </div>
+      {/* 表格主体 */}
+      <div className="tableMain">
+        <Table
+          scroll={{ y: 625 }}
+          dataSource={results.list}
+          columns={columns}
+          rowKey="id"
+          pagination={{
+            showQuickJumper: true,
+            position: ["bottomCenter"],
+            showSizeChanger: true,
+            current: tableSelect.pageNum,
+            pageSize: tableSelect.pageSize,
+            total: results.total,
+            onChange: paginationChange,
+          }}
+        />
+      </div>
+      {/* 修改积分 */}
+      <Modal
+        destroyOnClose
+        closable={false}
+        maskClosable={false}
+        open={editIntegralVisible}
+        title="   "
+        onCancel={() => setEditIntegralVisible(false)}
+        footer={
+          [] // 设置footer为空,去掉 取消 确定默认按钮
+        }
+      >
+        <Form
+          form={form}
+          name="basic"
+          labelCol={{ span: 8 }}
+          onFinish={onFinish}
+          autoComplete="off"
+        >
+          <Form.Item
+            label="积分变动"
+            name="numberVal"
+            style={{ marginTop: "40px" }}
+            rules={[{ required: true, message: "不能为空!" }]}
+            hide-required-asterisk={true}
+            getValueFromEvent={(e) =>
+              e.target.value.replace(/^(0+)|[^\d]+/g, "")
+            }
+          >
+            <Input
+              max={99999}
+              min={-99999}
+              placeholder="请输入-99999至99999的整数"
+            />
+          </Form.Item>
+          <Form.Item
+            label="积分原因"
+            style={{ marginTop: "40px" }}
+            hide-required-asterisk={true}
+          >
+            <Input maxLength={200} placeholder="请输入说明,不超过200字" />
+          </Form.Item>
+          {/* 确定和取消按钮 */}
+          <br />
+          <Form.Item wrapperCol={{ offset: 9, span: 16 }}>
+            <Button type="primary" htmlType="submit">
+              提交
+            </Button>
+            &emsp;
+            <Popconfirm
+              title="放弃编辑后,信息将不会保存!"
+              okText="放弃"
+              cancelText="取消"
+              onConfirm={() => {
+                setEditIntegralVisible(false);
+              }}
+              okButtonProps={{ loading: false }}
+            >
+              <Button>取消</Button>
+            </Popconfirm>
+          </Form.Item>
+        </Form>
+      </Modal>
+    </div>
+  );
+}
+
+const MemoIntegralEdit = React.memo(IntegralEdit);
+
+export default MemoIntegralEdit;

+ 32 - 3
houtai/src/pages/A6IDUser/index.module.scss

@@ -1,5 +1,34 @@
-.AAAAA{
-  :global{
-    
+.A6IDUser{
+  :global {
+    .logTop {
+      border-radius: 10px;
+      background-color: #fff;
+
+      .tableSelectBox {
+        padding: 15px 24px;
+        display: flex;
+        align-items: center;
+
+        .row {
+          margin-right: 20px;
+        }
+        .reSetBtn{
+          float: right;
+          height: 100%;
+        }
+      }
+    }
+
+    .tableMain {
+      border-radius: 10px;
+      margin-top: 15px;
+      height: calc(100% - 75px);
+      background-color: #fff;
+
+      .ant-table-body {
+        height: 500px;
+
+      }
+    }
   }
 }

+ 207 - 9
houtai/src/pages/A6IDUser/index.tsx

@@ -1,14 +1,212 @@
-import React from "react";
+import { RootState } from "@/store";
+import { getLogListAPI } from "@/store/action/A7Log";
+import { Input, DatePicker, Table, Button, Popconfirm } from "antd";
+import React, {
+  useCallback,
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+} from "react";
+import { useDispatch, useSelector } from "react-redux";
+import history from "@/utils/history";
 import styles from "./index.module.scss";
- function AAAAA() {
-  
-  return (
-    <div className={styles.AAAAA}>
-      <h1>AAAAA</h1>
+import { IDUserTableType } from "@/types/api/A6IDUser";
+import IntegralEdit from "./IntegralEdit";
+
+const { RangePicker } = DatePicker;
+
+function A6IDUser() {
+  const dispatch = useDispatch();
+
+  const pageNumRef = useRef(1);
+  const pagePageRef = useRef(10);
+  // 筛选和分页
+  const [tableSelect, setTableSelect] = useState({
+    searchKey: "",
+    pageSize: 10,
+    pageNum: 1,
+    startTime: "",
+    endTime: "",
+  });
+
+  // 账号的输入
+  const nameTime = useRef(-1);
+  const nameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+    clearTimeout(nameTime.current);
+    nameTime.current = window.setTimeout(() => {
+      setTableSelect({ ...tableSelect, searchKey: e.target.value, pageNum: 1 });
+    }, 500);
+  };
+  // 时间选择器改变
+  const timeChange = (date: any, dateString: any) => {
+    let startTime = "";
+    let endTime = "";
+    if (dateString[0] && dateString[1]) {
+      startTime = dateString[0] + " 00:00:00";
+      endTime = dateString[1] + " 23:59:59";
+    }
+    setTableSelect({ ...tableSelect, startTime, endTime, pageNum: 1 });
+  };
+
+  const [inputKey, setInputKey] = useState(1);
+  // 重置
+  const resetFu = () => {
+    setInputKey(Date.now());
+    setTableSelect({
+      searchKey: "",
+      pageSize: 10,
+      pageNum: 1,
+      startTime: "",
+      endTime: "",
+    });
+  };
+
+  // 点击跳转
+  const pathCutFu = useCallback((path: string) => {
+    history.push(path);
+  }, []);
+
+  useEffect(() => {
+    pageNumRef.current = tableSelect.pageNum;
+    pagePageRef.current = tableSelect.pageSize;
+    dispatch(getLogListAPI(tableSelect));
+  }, [dispatch, tableSelect]);
+
+  // ---------关于表格
+
+  // 页码变化
+  const paginationChange = (pageNum: number, pageSize: number) => {
+    pageNumRef.current = pageNum;
+    pagePageRef.current = pageSize;
+    setTableSelect({ ...tableSelect, pageNum, pageSize });
+  };
+
+  const [currentItem, setCurrentItem] = useState<IDUserTableType>({
+    id: 0,
+  } as IDUserTableType);
+
+  const results = useSelector((state: RootState) => state.A7Log.tableInfo);
+
+  const [editPageShow, setEditPageShow] = useState(false);
+
+  const columns = useMemo(() => {
+    return [
+      {
+        title: "用户名",
+        dataIndex: "userName",
+      },
+      {
+        title: "手机号",
+        dataIndex: "createTime",
+      },
+      {
+        title: "创建日期",
+        dataIndex: "ip",
+      },
+      {
+        title: "状态",
+        dataIndex: "description",
+      },
+      {
+        title: "当前积分",
+        dataIndex: "description",
+      },
+      {
+        title: "操作",
+        render: (item: IDUserTableType) => {
+          return (
+            <>
+              <Button
+                size="small"
+                type="text"
+                onClick={() => {
+                  setCurrentItem(item);
+                  setEditPageShow(true);
+                }}
+              >
+                积分管理
+              </Button>
+              <Popconfirm
+                title="是否将密码重置为123456?"
+                okText="确认"
+                cancelText="取消"
+                okButtonProps={{ loading: false }}
+              >
+                <Button type="text">重置密码</Button>
+              </Popconfirm>
+              <Popconfirm
+                title="是否将用户设为黑名单"
+                okText="确认"
+                cancelText="取消"
+                okButtonProps={{ loading: false }}
+              >
+                <Button type="text">设为黑名单</Button>
+              </Popconfirm>
+            </>
+          );
+        },
+      },
+    ];
+  }, []);
+
+  return !editPageShow ? (
+    <div className={styles.A6IDUser}>
+      <div className="pageTitle">用户管理</div>
+      <div className="logTop">
+        <div className="tableSelectBox">
+          <div className="row">
+            <span>用户名:</span>
+            <Input
+              key={inputKey}
+              maxLength={15}
+              style={{ width: 150 }}
+              placeholder="请输入"
+              allowClear
+              onChange={(e) => nameChange(e)}
+            />
+          </div>
+          <div className="row">
+            <span>日期:</span>
+            <RangePicker key={inputKey} onChange={timeChange} />
+          </div>
+          <Button
+            className="reSetBtn"
+            size="small"
+            type="primary"
+            onClick={() => {
+              resetFu();
+            }}
+          >
+            重置
+          </Button>
+        </div>
+      </div>
+
+      {/* 表格主体 */}
+      <div className="tableMain">
+        <Table
+          scroll={{ y: 625 }}
+          dataSource={results.list}
+          columns={columns}
+          rowKey="id"
+          pagination={{
+            showQuickJumper: true,
+            position: ["bottomCenter"],
+            showSizeChanger: true,
+            current: tableSelect.pageNum,
+            pageSize: tableSelect.pageSize,
+            total: results.total,
+            onChange: paginationChange,
+          }}
+        />
+      </div>
     </div>
-  )
+  ) : (
+    <IntegralEdit id={currentItem.id} closeFu={() => setEditPageShow(false)} />
+  );
 }
 
-const MemoAAAAA = React.memo(AAAAA);
+const MemoA6IDUser = React.memo(A6IDUser);
 
-export default MemoAAAAA;
+export default MemoA6IDUser;

+ 1 - 1
houtai/src/pages/C7Log/index.module.scss

@@ -22,7 +22,7 @@
       background-color: #fff;
 
       .ant-table-body {
-        height: 625px;
+        height: 500px;
 
       }
     }

+ 8 - 0
houtai/src/pages/Layout/index.tsx

@@ -74,6 +74,14 @@ function Layout() {
         inco: inco1,
         done: true,
       },
+      {
+        id: 104,
+        name: "题目设置",
+        path: "/topicSetting",
+        Com: React.lazy(() => import("../TopicSetting")),
+        inco: inco1,
+        done: false,
+      },
     ];
     return arr;
   }, []);

+ 5 - 0
houtai/src/pages/TopicSetting/index.module.scss

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

+ 14 - 0
houtai/src/pages/TopicSetting/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;

+ 35 - 7
houtai/src/store/action/A1Rule.ts

@@ -1,23 +1,51 @@
 import http from "@/utils/http";
 import { AppDispatch } from "..";
+import { SaveRuleType, SaveScoreLimitType } from "@/types";
 // import { AxiosRequestConfig } from "axios";
 /**
- * 获取浏览量信息
+ * 获取游戏规则列表
  */
-export const getShareAPI = () => {
+export const getRuleAPI = () => {
   return async (dispatch: AppDispatch) => {
     const res = await http.get(`cms/share/detail/museum_cctv_mianyan`);
     if (res.code === 0) {
       const data = res.data;
-      dispatch({ type: "Share/getShare", payload: data });
+      dispatch({ type: "rules/getList", payload: data });
     }
   };
 };
 
 /**
- * 提交参与者基数
+ * 修改游戏规则
  */
-export const shareEditAPI = (data: any) => {
-  // return http.post(`/cms/share/save/`, data);
-  return http.post(`cms/share/edit/`, data);
+export const ruleSaveAPI = (data: SaveRuleType) => {
+  return http.post("sys/user/save", data);
+};
+
+/**
+ * 获取游戏info
+ */
+export const getRuleInfoByIdAPI = (id: number) => {
+  return http.get(`sys/user/detail/${id}`);
+};
+
+/**
+ * 获得每日积分上限
+ */
+export const getScoreLimitAPI = () => {
+  return http.get("sys/user/save");
+};
+
+/**
+ * 保存每日积分上限
+ */
+export const scoreLimitSaveAPI = (data: SaveScoreLimitType) => {
+  return http.post("sys/user/save", data);
+};
+
+/**
+ * 获取助农课堂题目列表
+ */
+export const getTopicByZhuNongKeTangAPI = (data: any) => {
+  return http.post("sys/log/list", data);
 };

+ 30 - 5
houtai/src/store/action/A4Prise.ts

@@ -1,23 +1,48 @@
 import http from "@/utils/http";
 import { AppDispatch } from "..";
+import { AddPrizeType } from "@/types";
 // import { AxiosRequestConfig } from "axios";
 /**
- * 获取浏览量信息
+ * 获取奖品列表
  */
-export const getShareAPI = () => {
+export const getPrizeListAPI = () => {
   return async (dispatch: AppDispatch) => {
     const res = await http.get(`cms/share/detail/museum_cctv_mianyan`);
     if (res.code === 0) {
       const data = res.data;
-      dispatch({ type: "Share/getShare", payload: data });
+      dispatch({ type: "prise/getList", payload: data });
     }
   };
 };
 
 /**
- * 提交参与者基数
+ * 获得奖品详情
  */
-export const shareEditAPI = (data: any) => {
+export const getPrizeDetailAPI = (id: number) => {
+  // return http.post(`/cms/share/save/`, data);
+  return http.get(`cms/share/edit/id=${id}`);
+};
+
+/**
+ * 通过id删除奖品
+ */
+export const deletePrizeByIdAPI = (id: number) => {
+  // return http.post(`/cms/share/save/`, data);
+  return http.post(`cms/share/edit/`, { id: id });
+};
+
+/**
+ * 保存奖品编辑
+ */
+export const editPrizeByIdAPI = (data: AddPrizeType) => {
+  // return http.post(`/cms/share/save/`, data);
+  return http.post(`cms/share/edit/`, data);
+};
+
+/**
+ * 添加奖品
+ */
+export const addPrizeByIdAPI = (data: AddPrizeType) => {
   // return http.post(`/cms/share/save/`, data);
   return http.post(`cms/share/edit/`, data);
 };

+ 33 - 0
houtai/src/store/action/A6IDUser.ts

@@ -0,0 +1,33 @@
+import http from "@/utils/http";
+import { AppDispatch } from "..";
+import { SaveIDUserScoreType } from "@/types";
+/**
+ * 获取日志表格列表
+ */
+export const getIDUserListAPI = (data: any) => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post("sys/log/list", data);
+    if (res.code === 0) {
+      const obj = {
+        list: res.data.records,
+        total: res.data.total,
+      };
+      dispatch({ type: "iduser/getList", payload: obj });
+    }
+  };
+};
+
+/**
+ * 用户-获得用户积分记录
+ */
+export const getIDUserInfoByIdAPI = (id: number) => {
+  return http.get(`sys/user/editStatus/${id}`);
+};
+
+
+/**
+ * 保存用户积分修改
+ */
+export const IDUserScoreSaveAPI = (data: SaveIDUserScoreType) => {
+  return http.post("sys/user/save", data);
+};

+ 49 - 0
houtai/src/store/action/TopicSetting.ts

@@ -0,0 +1,49 @@
+import http from "@/utils/http";
+import { AppDispatch } from "..";
+import { SaveRuleType, SaveScoreLimitType } from "@/types";
+// import { AxiosRequestConfig } from "axios";
+/**
+ * 获取游戏规则列表
+ */
+export const getRuleAPI = () => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.get(`cms/share/detail/museum_cctv_mianyan`);
+    if (res.code === 0) {
+      const data = res.data;
+      dispatch({ type: "rules/getList", payload: data });
+    }
+  };
+};
+
+/**
+ * 修改游戏规则
+ */
+export const ruleSaveAPI = (data: SaveRuleType) => {
+  return http.post("sys/user/save", data);
+};
+
+/**
+ * 获取游戏info
+ */
+export const getRuleInfoByIdAPI = (id: number) => {
+  return http.get(`sys/user/detail/${id}`);
+};
+
+
+/**
+ * 获得每日积分上限
+ */
+export const getScoreLimitAPI = () => {
+  return http.get("sys/user/save");
+};
+
+
+/**
+ * 保存每日积分上限
+ */
+export const scoreLimitSaveAPI = (data: SaveScoreLimitType) => {
+  return http.post("sys/user/save", data);
+};
+
+
+

+ 7 - 6
houtai/src/store/reducer/A1Rule.ts

@@ -1,20 +1,21 @@
-import { GoodsTableType } from "@/types";
+import { RulesTableType } from "@/types";
 
 // 初始化状态
 const initState = {
   // 列表数据
   tableInfo: {
-    list: [] as GoodsTableType[],
+    list: [] as RulesTableType[],
     total: 0,
   },
 };
 
 // 定义 action 类型
 type GoodsActionType = {
-  type: "goods/getList";
-  payload: { list: GoodsTableType[]; total: number };
+  type: "rules/getList";
+  payload: { list: RulesTableType[]; total: number };
 };
 
+
 // 频道 reducer
 export default function goodsReducer(
   state = initState,
@@ -22,9 +23,9 @@ export default function goodsReducer(
 ) {
   switch (action.type) {
     // 获取列表数据
-    case "goods/getList":
+    case "rules/getList":
       return { ...state, tableInfo: action.payload };
     default:
       return state;
   }
-}
+}

+ 3 - 3
houtai/src/store/reducer/A2Integral.ts

@@ -1,15 +1,15 @@
-import { ShareDataAPIType } from "@/types";
+import { IntegralTableAPIType } from "@/types";
 
 // 初始化状态
 const initState = {
   // 分享数据
-  shareInfo: {} as ShareDataAPIType,
+  shareInfo: {} as IntegralTableAPIType,
 };
 
 // 定义 action 类型
 type ShareActionType = {
   type: "Share/getShare";
-  payload: ShareDataAPIType;
+  payload: IntegralTableAPIType;
 };
 
 // 频道 reducer

+ 5 - 5
houtai/src/store/reducer/A4Prise.ts

@@ -1,18 +1,18 @@
-import { GoodsTableType } from "@/types";
+import { PrizeTableType } from "@/types";
 
 // 初始化状态
 const initState = {
   // 列表数据
   tableInfo: {
-    list: [] as GoodsTableType[],
+    list: [] as PrizeTableType[],
     total: 0,
   },
 };
 
 // 定义 action 类型
 type GoodsActionType = {
-  type: "goods/getList";
-  payload: { list: GoodsTableType[]; total: number };
+  type: "prise/getList";
+  payload: { list: PrizeTableType[]; total: number };
 };
 
 // 频道 reducer
@@ -22,7 +22,7 @@ export default function goodsReducer(
 ) {
   switch (action.type) {
     // 获取列表数据
-    case "goods/getList":
+    case "prise/getList":
       return { ...state, tableInfo: action.payload };
     default:
       return state;

+ 27 - 0
houtai/src/store/reducer/A6IDUser.ts

@@ -0,0 +1,27 @@
+import { IDUserTableType } from "@/types";
+
+// 初始化状态
+const initState = {
+  // 列表数据
+  tableInfo: {
+    list: [] as IDUserTableType[],
+    total: 0,
+  },
+};
+
+// 定义 action 类型
+type IDUserActionType = {
+  type: "iduser/getList";
+  payload: { list: IDUserTableType[]; total: number };
+};
+
+// 频道 reducer
+export default function logReducer(state = initState, action: IDUserActionType) {
+  switch (action.type) {
+    // 获取列表数据
+    case "iduser/getList":
+      return { ...state, tableInfo: action.payload };
+    default:
+      return state;
+  }
+}

+ 31 - 0
houtai/src/store/reducer/TopicSetting.ts

@@ -0,0 +1,31 @@
+import { RulesTableType } from "@/types";
+
+// 初始化状态
+const initState = {
+  // 列表数据
+  tableInfo: {
+    list: [] as RulesTableType[],
+    total: 0,
+  },
+};
+
+// 定义 action 类型
+type GoodsActionType = {
+  type: "rules/getList";
+  payload: { list: RulesTableType[]; total: number };
+};
+
+
+// 频道 reducer
+export default function goodsReducer(
+  state = initState,
+  action: GoodsActionType
+) {
+  switch (action.type) {
+    // 获取列表数据
+    case "rules/getList":
+      return { ...state, tableInfo: action.payload };
+    default:
+      return state;
+  }
+}

+ 8 - 1
houtai/src/store/reducer/index.ts

@@ -6,6 +6,10 @@ import { combineReducers } from 'redux'
 import A1Rule from './A1Rule'
 import A0Layout from './layout'
 import A3User from './A3User'
+import A4Prise from './A4Prise'
+import TopicSetting from './TopicSetting'
+
+import A6IDUser from './A6IDUser'
 import A7Log from './A7Log'
 import A2Integral from './A2Integral'
 
@@ -14,8 +18,11 @@ const rootReducer = combineReducers({
   A1Rule,
   A0Layout,
   A3User,
+  A4Prise,
   A7Log,
-  A2Integral
+  A2Integral,
+  TopicSetting,
+  A6IDUser
 })
 
 // 默认导出

+ 57 - 0
houtai/src/types/api/A1Rule.ts

@@ -0,0 +1,57 @@
+export type RulesTableType = {
+  createTime: string;
+  creatorId: number;
+  creatorName: string;
+  description: string;
+  dictAge: string;
+  dictLevel: string;
+  dictSource: string;
+  dictTexture: string;
+  dirCode: string;
+  display: number;
+  fileIds: string;
+  id: number;
+  isBarrage: number;
+  name: string;
+  num: string;
+  thumb: string;
+  topic: string;
+  type: string;
+  updateTime: string;
+  tagType?: string;
+  tagCountry?: string;
+};
+
+export type FileListType = {
+  fileName?: string;
+  filePath?: string;
+  id?: number;
+  isFrame?: boolean;
+  done?: boolean;
+  type?: "model" | "img" | "audio" | "video";
+};
+
+export type FileImgListType = {
+  id: number;
+  fileName: string;
+  filePath: string;
+};
+
+
+
+export type SaveRuleType ={
+  id:number|null
+  userName:string
+  nickName:string
+  roleId:number
+  realName:string
+}
+
+
+export type SaveScoreLimitType ={
+  id:number|null
+  userName:string
+  nickName:string
+  roleId:number
+  realName:string
+}

+ 3 - 1
houtai/src/types/api/A2Share.d.ts

@@ -1,4 +1,4 @@
-export type ShareDataAPIType = {
+export type IntegralTableAPIType = {
   createTime: string;
   creatorId: number;
   creatorName: string;
@@ -13,6 +13,8 @@ export type ShareDataAPIType = {
   pcsArea: number;
   sceneCode: string;
   updateTime: string;
+  explain: string;
+  type: string;
 };
 // export type ShareDataAPIType = {
 //   createTime: string;

+ 29 - 0
houtai/src/types/api/A4Prize.ts

@@ -0,0 +1,29 @@
+export type PrizeTableType = {
+  count: number;
+  createTime: string;
+  creatorId: null;
+  creatorName: string;
+  id: number;
+  isEnabled: number;
+  roleDesc: string;
+  roleKey: string;
+  roleName: string;
+  sort: string;
+  updateTime: string;
+  thumb: string;
+};
+
+export type PermissionsAPIType = {
+  authority: boolean;
+  id: number;
+  name: string;
+  parentId?: null;
+  resourceType?: string;
+};
+
+export type AddPrizeType = {
+  id: number | null;
+  roleName: string;
+  roleDesc: string;
+  resources: number[];
+};

+ 38 - 0
houtai/src/types/api/A6IDUser.ts

@@ -0,0 +1,38 @@
+export type IDUserTableType = {
+  createTime: string;
+  creatorId: null;
+  creatorName: string;
+  description: string;
+  id: number;
+  ip: string;
+  type: string;
+  updateTime: null;
+  userName: string;
+}
+
+
+export type IDUserType = {
+  createTime: string;
+  creatorId: null;
+  creatorName: string;
+  description: string;
+  id: number;
+  ip: string;
+  type: string;
+  updateTime: null;
+  userName: string;
+  name: string;
+}
+
+export type SaveIDUserScoreType = {
+  createTime: string;
+  creatorId: null;
+  creatorName: string;
+  description: string;
+  id: number;
+  ip: string;
+  type: string;
+  updateTime: null;
+  userName: string;
+  name: string;
+}

+ 38 - 0
houtai/src/types/api/TopicSetting.ts

@@ -0,0 +1,38 @@
+export type GoodsTableType = {
+  createTime: string;
+  creatorId: number;
+  creatorName: string;
+  description: string;
+  dictAge: string;
+  dictLevel: string;
+  dictSource: string;
+  dictTexture: string;
+  dirCode: string;
+  display: number;
+  fileIds: string;
+  id: number;
+  isBarrage: number;
+  name: string;
+  num: string;
+  thumb: string;
+  topic: string;
+  type: string;
+  updateTime: string;
+  tagType?: string;
+  tagCountry?: string;
+};
+
+export type FileListType = {
+  fileName?: string;
+  filePath?: string;
+  id?: number;
+  isFrame?: boolean;
+  done?: boolean;
+  type?: "model" | "img" | "audio" | "video";
+};
+
+export type FileImgListType = {
+  id: number;
+  fileName: string;
+  filePath: string;
+};

+ 1 - 0
houtai/src/types/declaration.d.ts

@@ -4,3 +4,4 @@ declare module "*.png";
 declare module "*.jpg";
 declare module "*.gif";
 declare module "js-export-excel";
+declare module 'braft-utils';

+ 5 - 1
houtai/src/types/index.d.ts

@@ -1,8 +1,12 @@
 export * from './api/layot'
+export * from './api/A1Rule'
 export * from './api/A1Goods'
+export * from './api/A2Integral'
 export * from './api/A3User'
 export * from './api/A4Role'
+export * from './api/A4Prize'
 export * from './api/A5Log'
-export * from './api/A2Share'
+export * from './api/A6IDUser'
+export * from './api/A2Integral'
 
 

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 43 - 19
zhengquan/public/staticData/data.js


BIN
zhengquan/public/staticData/icon/xuting.png


BIN
zhengquan/public/staticData/thumbnail/img-1.png


BIN
zhengquan/public/staticData/thumbnail/img-gonyi.png


BIN
zhengquan/public/staticData/thumbnail/img-weiting.png


BIN
zhengquan/public/staticData/thumbnail/img-xuting.png


+ 4 - 0
zhengquan/src/App.vue

@@ -13,7 +13,9 @@ onMounted(() => {
   window.addEventListener(
     "resize",
     () => {
+      //@ts-ignore
       clearTimeout(time.current);
+      //@ts-ignore
       time.current = window.setTimeout(() => {
         // 根元素
         const dom: HTMLDivElement | null = document.querySelector("#app");
@@ -36,10 +38,12 @@ onMounted(() => {
   font-family: 'AlibabaPuHuiTi2.0-105Heavy';
   src: url('./assets/fonts/AlibabaPuHuiTi2.0-105Heavy.ttf');
 }
+
 @font-face {
   font-family: 'SourceHanSansCN-Medium';
   src: url('./assets/fonts/SourceHanSansCN-Medium.otf');
 }
+
 @font-face {
   font-family: 'AlibabaPuHuiTi2.0-75SemiBold';
   src: url('./assets/fonts//AlibabaPuHuiTi2.0-75SemiBold.ttf');

BIN
zhengquan/src/assets/images/home/bg1-1open.png


BIN
zhengquan/src/assets/images/home/bg1open.png


BIN
zhengquan/src/assets/images/home/bg3.png


BIN
zhengquan/src/assets/images/home/bg3open.png


BIN
zhengquan/src/assets/images/home/icon-down.png


BIN
zhengquan/src/assets/images/home/icon-up-mo.png


+ 7 - 0
zhengquan/src/images.d.ts

@@ -0,0 +1,7 @@
+declare module '*.svg'
+declare module '*.png'
+declare module '*.jpg'
+declare module '*.jpeg'
+declare module '*.gif'
+declare module '*.bmp'
+declare module '*.tiff'

+ 1 - 0
zhengquan/src/utils/browser.ts

@@ -28,6 +28,7 @@ function versions () {
     // 是否为微信浏览器
     weixin: ~u.indexOf('MicroMessenger'),
     // 获取浏览器语言
+    // @ts-ignore
     language: (navigator.browserLanguage || navigator.language).toLowerCase()
   }
 }

+ 2 - 2
zhengquan/src/utils/https.ts

@@ -1,7 +1,7 @@
 // 本地开发
-const baseUrl = "/staticData";
+// const baseUrl = "/staticData";
 
 // 线上开发
-// const baseUrl = './staticData'
+const baseUrl = './staticData'
 
 export default baseUrl;

+ 0 - 28
zhengquan/src/utils/loadScript.ts

@@ -1,28 +0,0 @@
-//动态加载外部js
-//@param RESOURCE_LIST 外部地址集合["address"]
-export function loadVoLteResourceList(RESOURCE_LIST: any, success: any) {
-  return new Promise((r) => {
-    RESOURCE_LIST.reduce((res: any, el: any) => res.then(() => loadScript(el)), Promise.resolve())
-      .then(() => {
-        r()
-      })
-      .catch((error: any) => {
-        console.error('外呼VoLTE sdk 前置 js 资源加载失败:', error.name, error.message)
-        return Promise.reject(error)
-      })
-  })
-}
-
-export function loadScript(url: string) {
-  return new Promise((resolve, reject) => {
-    const script = document.createElement('script')
-
-    script.onload = () => resolve()
-
-    script.onerror = () => reject(new Error(`Load script from ${url} failed`))
-
-    script.src = url
-    const head = document.head || document.getElementsByTagName('head')[0]
-    ;(document.body || head).appendChild(script)
-  })
-}

+ 163 - 52
zhengquan/src/views/Home/components/homeTabbar.vue

@@ -26,6 +26,8 @@ const openUnit = () => {
   isOpenSceneList.value = false
 };
 
+const openMo = ref(false)
+
 </script>
 
 <template>
@@ -60,63 +62,77 @@ const openUnit = () => {
       </div>
     </div>
   </div>
-  <div v-else class="tabbar-box-mo">
-    <!-- 左箭头 -->
-    <div class="arrows-left-mo" v-show="startItemMo != 0" @click="startItemMo -= 1">
-      <img src="@/assets/images/home/arrows-left-mo-icon.png" alt="">
-    </div>
-    <!-- 公益单位 -->
-    <div class="gonyi" v-show="startItemMo == 0">
-      <img class="item-bg" src="@/assets/images/home/bg0.png" alt="">
-      <div class="item-con">
-        <img :src="isOpenSceneList ? IconGy : IconGyAc" alt="">
-        <div @click="openUnit">公益单位</div>
-      </div>
-    </div>
-    <div class="gonyi" v-for="(item, index) in 3" :key="index">
-      <!-- 在第一位 -->
-      <img v-if="startItemMo != 0 && index == 0" class="item-bg" src="@/assets/images/home/bg1-1.png" alt="">
-      <img v-else class="item-bg" src="@/assets/images/home/bg1.png" alt="">
-      <img v-show="startItemMo + index == store.dataAll.sceneList.length - 1" src="" alt="">
-      <div class="item-con">
-        <img :src="`${baseUrl}/icon/${store.dataAll.sceneList[startItemMo + index].icon}`" alt="">
-        <div @click="openUnit">{{ store.dataAll.sceneList[startItemMo + index].name }}</div>
+  <div v-else>
+    <div v-if="!openMo">
+      <!-- 上箭头 -->
+      <img class="up-icon" src="@/assets/images/home/icon-up-mo.png" alt="" @click="openMo = true">
+      <div class="tabbar-box-mo">
+        <!-- 左箭头 -->
+        <div class="arrows-left-mo" v-show="startItemMo != 0" @click="startItemMo -= 1">
+          <img src="@/assets/images/home/arrows-left-mo-icon.png" alt="">
+        </div>
+        <!-- 公益单位 -->
+        <div class="gonyi" v-show="startItemMo == 0" @click="openUnit">
+          <img class="item-bg" src="@/assets/images/home/bg0.png" alt="">
+          <div class="item-con">
+            <img :src="isOpenSceneList ? IconGy : IconGyAc" alt="">
+            <div>公益单位</div>
+          </div>
+        </div>
+        <div class="gonyi" v-for="(item, index) in 3" :key="index"
+          @click="() => { router.push({ name: 'scene', query: { code: store.dataAll.sceneList[startItem + item - 1].code } }) }">
+          <!-- 在第一位 -->
+          <img v-if="startItemMo != 0 && index == 0" class="item-bg" src="@/assets/images/home/bg1-1.png" alt="">
+          <img v-else v-show="startItemMo + index != store.dataAll.sceneList.length - 1" class="item-bg"
+            src="@/assets/images/home/bg1.png" alt="">
+          <img class="item-bg-last" v-show="startItemMo + index == store.dataAll.sceneList.length - 1"
+            src="@/assets/images/home/bg3.png" alt="">
+          <div class="item-con">
+            <img :src="`${baseUrl}/icon/${store.dataAll.sceneList[startItemMo + index].icon}`" alt="">
+            <div>{{ store.dataAll.sceneList[startItemMo + index].name }}</div>
+          </div>
+          <div class="item-numbser" v-show="startItemMo + index != store.dataAll.sceneList.length - 1">{{ startItemMo +
+            index
+            + 1 }}</div>
+        </div>
+        <!-- 右箭头 -->
+        <div class="arrows-right-mo" @click="startItemMo += 1" v-show="startItemMo + 3 < store.dataAll.sceneList.length">
+          <img src="@/assets/images/home/arrows-right-mo-icon.png" alt="">
+        </div>
       </div>
-      <div class="item-numbser" v-show="startItemMo + index != store.dataAll.sceneList.length - 1">{{ startItemMo + index + 1 }}</div>
-    </div>
-    <!-- 右箭头 -->
-    <div class="arrows-right-mo" @click="startItemMo += 1" v-show="startItemMo + 3 < store.dataAll.sceneList.length">
-      <img src="@/assets/images/home/arrows-right-mo-icon.png" alt="">
     </div>
-    <!-- 公益单位 -->
-    <!-- <div class="gonyi">
-      <img :src="isOpenSceneList ? IconGy : IconGyAc" alt="">
-      <div style="margin-top: -2vh;" @click="openUnit">公益单位</div>
-    </div> -->
-    <!-- <div class="scene-box">
-      <div class="scene-icon">
-        <img :src="isOpenSceneList ? IconGy : IconGyAc" alt="">
-        <div style="margin-top: -2vh;" @click="openUnit">公益单位</div>
-      </div>
-      <div class="scene-list">
-        <img class="icon-up" src="@/assets/images/home/icon-up-mo.png" alt="">
-        <div class="list-item">
-          <img class="item-bg" v-show="index == 0" src="@/assets/images/home/bg1.png" alt="">
-          <img :src="isOpenSceneList ? IconGy : IconGyAc" alt="">
-          <div style="margin-top: -2vh;" @click="openUnit">公益单位</div>
+    <div v-else>
+      <!-- 下箭头 -->
+      <img class="down-icon" src="@/assets/images/home/icon-down.png" alt="" @click="openMo = false">
+      <div class="tabbar-box-mo open">
+        <div class="open-name">
+          虚拟展厅
         </div>
-        <div class="list-item" v-for="(item, index) in store.dataAll.sceneList" :key="index">
-          <div class="number-icon" v-show="index != store.dataAll.sceneList.length - 1">{{ index + 1 }}</div>
-          <img class="item-bg" v-show="index == 0" src="@/assets/images/home/bg1.png" alt="">
-          <img class="item-bg" v-show="index != 0 && index != store.dataAll.sceneList.length - 1"
-            src="@/assets/images/home/bg2.png" alt="">
-          <img class="item-bg" v-show="index == store.dataAll.sceneList.length - 1" src="@/assets/images/home/bg3.png"
-            alt="">
-          <img :src="`${baseUrl}/icon/${item.icon}`" alt="">
-          <div style="margin-top: -2vh;">{{ item.name }}</div>
+        <div class="scene-list">
+          <div class="scene-list-item" @click="openUnit">
+            <img class="item-bg" style="border-top-left-radius: 60px" src="@/assets/images/home/bg1-1open.png" alt="">
+            <!-- 封面 -->
+            <div class="thumb-img"
+              :style="{ background: `url(${baseUrl}/thumbnail/img-gonyi.png`, backgroundSize: 'cover' }"></div>
+            <div class="item-name">公益单位</div>
+            <div class="item-numbser">1</div>
+          </div>
+          <div class="scene-list-item" v-for="(item, index) in store.dataAll.sceneList" :key="index"
+            @click="() => { router.push({ name: 'scene', query: { code: store.dataAll.sceneList[index].code } }) }">
+            <img v-show="index != store.dataAll.sceneList.length - 1" class="item-bg"
+              src="@/assets/images/home/bg1open.png" alt="">
+            <img v-show="index == store.dataAll.sceneList.length - 1" class="item-bg"
+              src="@/assets/images/home/bg3open.png" alt="">
+            <!-- 封面 -->
+            <div class="thumb-img"
+              :style="{ background: `url(${baseUrl}/thumbnail/${item.thumbnail})`, backgroundSize: 'cover' }"></div>
+            <div class="item-name">{{ store.dataAll.sceneList[startItemMo + index].name }}</div>
+            <div class="item-numbser" v-show="startItemMo + index != store.dataAll.sceneList.length - 1">{{ index + 2 }}
+            </div>
+          </div>
         </div>
       </div>
-    </div> -->
+    </div>
   </div>
 </template>
 
@@ -256,6 +272,13 @@ const openUnit = () => {
 }
 
 @media screen and(max-width: 400px) {
+
+  .up-icon {
+    position: absolute;
+    bottom: 23vh;
+    left: 50%;
+  }
+
   .tabbar-box-mo {
     width: 90%;
     position: absolute;
@@ -275,6 +298,8 @@ const openUnit = () => {
     // justify-content: left;
     // align-items: end;
 
+
+
     .gonyi {
       width: 30vw;
       height: 100%;
@@ -291,6 +316,15 @@ const openUnit = () => {
         margin-right: -10px;
       }
 
+      .item-bg-last {
+        width: 32vw;
+        position: absolute;
+        top: 0;
+        left: 0;
+        filter: blur(1px);
+        margin-right: -10px;
+      }
+
       .item-con {
         width: 90%;
         height: 100%;
@@ -391,5 +425,82 @@ const openUnit = () => {
 
 
   }
+
+  .down-icon {
+    position: absolute;
+    top: calc(97.5vw);
+    left: 50%;
+  }
+
+  .open {
+    height: 42vh;
+    background: linear-gradient(#bc121b63, rgba(0, 0, 0, 0.644));
+    font-family: 'AlibabaPuHuiTi2.0-105Heavy';
+    padding: 0;
+
+    .open-name {
+      width: 100%;
+      height: 8vh;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      color: white;
+    }
+
+    .scene-list {
+      width: 90%;
+      height: 35vh;
+      // background: red;
+      padding: 0 15px;
+      display: flex;
+      justify-content: left;
+      overflow-x: auto;
+      overflow-y: hidden;
+
+      &::-webkit-scrollbar {
+        width: 0;
+      }
+
+      .scene-list-item {
+        width: 30%;
+        position: relative;
+
+        .thumb-img {
+          width: 93%;
+          height: 65%;
+          position: absolute;
+          top: 0;
+          left: 8%;
+        }
+
+        .item-bg {
+          // width: 100%;
+          height: 92%;
+          transform: scale(1.14);
+          filter: blur(1px);
+        }
+
+        .item-name {
+          position: absolute;
+          color: white;
+          bottom: 21%;
+          left: 55%;
+          transform: translateX(-50%);
+          font-size: 13px;
+
+        }
+
+        .item-numbser {
+          color: #C5A16C;
+          font-family: 'SourceHanSansCN-Medium';
+          position: absolute;
+          font-size: .8em;
+          right: -5%;
+          bottom: 20%;
+        }
+      }
+
+    }
+  }
 }
 </style>

+ 10 - 9
zhengquan/src/views/Home/components/sceneListInfo.vue

@@ -24,6 +24,7 @@ onMounted(() => {
     slidesPerView: 5,
     allowSwipeToPrev: true,
     allowSwipeToNext: true,
+    // @ts-ignore
     direction: getDirection(),
     navigation: {
       nextEl: '.swiper-button-next',
@@ -36,15 +37,15 @@ onMounted(() => {
     },
   });
 })
-const swiperPrev = () => {
-  console.log('下一页')
-  swiper.slidePrev()
-}
-const swiperNext = () => {
-  console.log('上一页')
-  swiper.slideNext()
-
-}
+// const swiperPrev = () => {
+//   console.log('下一页')
+//   swiper.slidePrev()
+// }
+// const swiperNext = () => {
+//   console.log('上一页')
+//   swiper.slideNext()
+
+// }
 </script>
 
 <template>

+ 1 - 1
zhengquan/src/views/Home/components/unitList.vue

@@ -184,7 +184,7 @@ const swiperNext = () => {
         <div class="swiper-button-next" @click="swiper2Next"></div>
         <div class="swiper-pagination2"></div>
         <div class="pagination2">
-          <div class="pagination2-item" v-for="(item, index) in curUnit.images" :key="index"
+          <div class="pagination2-item" v-for="(item, index) in curUnit.images" :key="item"
             @click="swiper2.slideTo(index)" :class="{ 'active': swiper2Index == index }">
           </div>
         </div>

+ 4 - 2
zhengquan/src/views/Scene/ScenePage.vue

@@ -32,6 +32,7 @@ const getAllHotspot = () => {
   store.dataAll.sceneList.forEach((item: any) => {
     axios.get(`https://super.4dage.com/data/${item.code}/data2.js?m=${new Date().getTime()}`).then((res: any) => {
       console.log('热点列表', res.data)
+      //@ts-ignore
       hotspots.value.push({
         id: item.id,
         unit: item.name,
@@ -52,6 +53,7 @@ watch(hotspots.value, (newVal: any) => {
 
 const goHotCamarer = (hot: any) => {
   const iframe = document.getElementById('sceneiframe') as HTMLIFrameElement
+  //@ts-ignore
   iframe.contentWindow.initCamera(hot.sid)
   currentHot.value = hot
   isShowHosList.value = false
@@ -72,7 +74,7 @@ onMounted(() => {
   // greeting-招呼 idle-静默 talk-说话
   window.handleRobot = (state: string) => {
     console.log('handleRobot!!!', state);
-    
+
     animalStat.value = state
     isReady.value = true
   }
@@ -87,7 +89,7 @@ onMounted(() => {
 
 <template>
   <div class='all'>
-    <iframe id="sceneiframe" :src="`/scene/index.html?m=${currentUnit.code}`"></iframe>
+    <iframe id="sceneiframe" :src="`./scene/index.html?m=${currentUnit.code}`"></iframe>
     <!-- 热点列表 -->
     <div v-show="isShowHosList" class="hots-box">
       <img v-show="browser.mobile" @click="isShowHosList = false" class="close-icon" src="@/assets/images/close-icon.png"

+ 0 - 1
zhengquan/tsconfig.json

@@ -27,5 +27,4 @@
     },
   },
   "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
-  "references": [{ "path": "./tsconfig.node.json" }]
 }