guhongwei 4 years ago
parent
commit
1f8d08a14a
100 changed files with 3000 additions and 197 deletions
  1. 2 0
      .env
  2. 33 0
      .eslintrc.js
  3. 125 9
      package-lock.json
  4. 8 1
      package.json
  5. 1 26
      src/App.vue
  6. BIN
      src/assets/2.jpg
  7. BIN
      src/assets/3.png
  8. BIN
      src/assets/achieve.png
  9. BIN
      src/assets/bg1.jpg
  10. BIN
      src/assets/center/cgxx.png
  11. BIN
      src/assets/center/gqxx.png
  12. BIN
      src/assets/center/jlhd.png
  13. BIN
      src/assets/center/sjdt.png
  14. BIN
      src/assets/center/xqxx.png
  15. BIN
      src/assets/cha.png
  16. BIN
      src/assets/directBack.png
  17. BIN
      src/assets/dynamic/1.png
  18. BIN
      src/assets/dynamic/2.png
  19. BIN
      src/assets/dynamic/3.png
  20. BIN
      src/assets/dynamic/4.png
  21. BIN
      src/assets/emotion/flower.gif
  22. BIN
      src/assets/emotion/flower2.gif
  23. BIN
      src/assets/emotion/hand.gif
  24. BIN
      src/assets/emotion/touxiang.png
  25. BIN
      src/assets/erweima.jpg
  26. BIN
      src/assets/expert.png
  27. BIN
      src/assets/fmzl.jpg
  28. BIN
      src/assets/fmzl1.jpg
  29. BIN
      src/assets/hall.jpg
  30. BIN
      src/assets/kjpd.png
  31. BIN
      src/assets/kjzx.jpg
  32. BIN
      src/assets/live/222.png
  33. BIN
      src/assets/live/d10_fbb1.png
  34. BIN
      src/assets/live/dock_top.png
  35. BIN
      src/assets/live/free-qrcode.jpg
  36. BIN
      src/assets/live/logo.png
  37. BIN
      src/assets/live/main1.png
  38. BIN
      src/assets/live/menu_back.jpg
  39. BIN
      src/assets/live/square_big.png
  40. BIN
      src/assets/live/top_bg.png
  41. BIN
      src/assets/login.jpg
  42. BIN
      src/assets/logo.png
  43. BIN
      src/assets/personal.jpg
  44. BIN
      src/assets/personalLive.jpg
  45. BIN
      src/assets/product.png
  46. BIN
      src/assets/square_big.png
  47. BIN
      src/assets/sx.png
  48. BIN
      src/assets/techolchat/fb.png
  49. BIN
      src/assets/techolchat/jy.png
  50. BIN
      src/assets/techolchat/lbyx.png
  51. BIN
      src/assets/techolchat/wsdc.png
  52. BIN
      src/assets/techolchat/zhfw.png
  53. BIN
      src/assets/techolchat/zxzx.png
  54. BIN
      src/assets/top_bg.png
  55. BIN
      src/assets/train.jpg
  56. BIN
      src/assets/video1.mp4
  57. BIN
      src/assets/video2.mp4
  58. BIN
      src/assets/技术成果1.png
  59. 0 130
      src/components/HelloWorld.vue
  60. 60 0
      src/components/common/foot.vue
  61. 42 0
      src/components/common/frame.vue
  62. 182 0
      src/components/common/top.vue
  63. 50 0
      src/components/frame/filter-page-table.md
  64. 312 0
      src/components/frame/filter-page-table.vue
  65. 82 0
      src/components/frame/form.md
  66. 211 0
      src/components/frame/form.vue
  67. 11 0
      src/components/frame/pagination.md
  68. 51 0
      src/components/frame/pagination.vue
  69. 172 0
      src/components/frame/swiper-frame.md
  70. 64 0
      src/components/frame/swiper-frame.vue
  71. 120 0
      src/components/frame/upload.vue
  72. 264 0
      src/components/frame/vform.vue
  73. 77 0
      src/components/frame/wang-editor.vue
  74. 119 0
      src/components/upload/uploadArray.vue
  75. 6 6
      src/main.js
  76. 2 14
      src/router/index.js
  77. 38 0
      src/store/category.js
  78. 53 0
      src/store/channel.js
  79. 53 0
      src/store/channelVideo.js
  80. 40 0
      src/store/code.js
  81. 43 0
      src/store/column.js
  82. 63 0
      src/store/dock.js
  83. 44 0
      src/store/dockPw.js
  84. 62 0
      src/store/dockUser.js
  85. 57 0
      src/store/expert.js
  86. 0 11
      src/store/index.js
  87. 43 0
      src/store/interview.js
  88. 26 0
      src/store/inviteCode.js
  89. 43 0
      src/store/menu.js
  90. 43 0
      src/store/news.js
  91. 43 0
      src/store/notice.js
  92. 57 0
      src/store/organization.js
  93. 43 0
      src/store/patent.js
  94. 61 0
      src/store/personal.js
  95. 43 0
      src/store/place.js
  96. 43 0
      src/store/product.js
  97. 43 0
      src/store/roadShow.js
  98. 43 0
      src/store/science.js
  99. 22 0
      src/store/statistics.js
  100. 0 0
      src/store/survey.js

+ 2 - 0
.env

@@ -0,0 +1,2 @@
+VUE_APP_AXIOS_BASE_URL = ''
+VUE_APP_ROUTER="/platlive"

+ 33 - 0
.eslintrc.js

@@ -0,0 +1,33 @@
+// https://eslint.org/docs/user-guide/configuring
+
+module.exports = {
+  root: true,
+  env: {
+    node: true,
+  },
+  extends: ['plugin:vue/essential', '@vue/prettier'],
+  plugins: ['vue'],
+  rules: {
+    'max-len': [
+      'warn',
+      {
+        code: 250,
+      },
+    ],
+    'no-unused-vars': 'off',
+    'no-console': 'off',
+    'prettier/prettier': [
+      'warn',
+      {
+        singleQuote: true,
+        trailingComma: 'es5',
+        bracketSpacing: true,
+        jsxBracketSameLine: true,
+        printWidth: 160,
+      },
+    ],
+  },
+  parserOptions: {
+    parser: 'babel-eslint',
+  },
+};

+ 125 - 9
package-lock.json

@@ -981,11 +981,19 @@
       "version": "7.12.13",
       "resolved": "https://registry.npm.taobao.org/@babel/runtime/download/@babel/runtime-7.12.13.tgz",
       "integrity": "sha1-CiFFI1KwJULbD/uSisLTyny21m0=",
-      "dev": true,
       "requires": {
         "regenerator-runtime": "^0.13.4"
       }
     },
+    "@babel/runtime-corejs3": {
+      "version": "7.12.13",
+      "resolved": "https://registry.npm.taobao.org/@babel/runtime-corejs3/download/@babel/runtime-corejs3-7.12.13.tgz?cache=0&sync_timestamp=1612314633178&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fruntime-corejs3%2Fdownload%2F%40babel%2Fruntime-corejs3-7.12.13.tgz",
+      "integrity": "sha1-U9CYE7fCDWFsryWOkyVVD/cBwDk=",
+      "requires": {
+        "core-js-pure": "^3.0.0",
+        "regenerator-runtime": "^0.13.4"
+      }
+    },
     "@babel/template": {
       "version": "7.12.13",
       "resolved": "https://registry.npm.taobao.org/@babel/template/download/@babel/template-7.12.13.tgz",
@@ -2338,6 +2346,14 @@
       "integrity": "sha1-3TeelPDbgxCwgpH51kwyCXZmF/0=",
       "dev": true
     },
+    "async-validator": {
+      "version": "1.8.5",
+      "resolved": "https://registry.npm.taobao.org/async-validator/download/async-validator-1.8.5.tgz?cache=0&sync_timestamp=1605751798748&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fasync-validator%2Fdownload%2Fasync-validator-1.8.5.tgz",
+      "integrity": "sha1-3D4I7B/Q3dtn5ghC8CwM0c7G1/A=",
+      "requires": {
+        "babel-runtime": "6.x"
+      }
+    },
     "asynckit": {
       "version": "0.4.0",
       "resolved": "https://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz",
@@ -2377,6 +2393,14 @@
       "integrity": "sha1-1h9G2DslGSUOJ4Ta9bCUeai0HFk=",
       "dev": true
     },
+    "axios": {
+      "version": "0.21.1",
+      "resolved": "https://registry.npm.taobao.org/axios/download/axios-0.21.1.tgz?cache=0&sync_timestamp=1608609419814&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Faxios%2Fdownload%2Faxios-0.21.1.tgz",
+      "integrity": "sha1-IlY0gZYvTWvemnbVFu8OXTwJsrg=",
+      "requires": {
+        "follow-redirects": "^1.10.0"
+      }
+    },
     "babel-eslint": {
       "version": "10.1.0",
       "resolved": "https://registry.npm.taobao.org/babel-eslint/download/babel-eslint-10.1.0.tgz",
@@ -2391,6 +2415,11 @@
         "resolve": "^1.12.0"
       }
     },
+    "babel-helper-vue-jsx-merge-props": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npm.taobao.org/babel-helper-vue-jsx-merge-props/download/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
+      "integrity": "sha1-Iq69OzOQIyjlEyk6jkmSs4T58bY="
+    },
     "babel-loader": {
       "version": "8.2.2",
       "resolved": "https://registry.npm.taobao.org/babel-loader/download/babel-loader-8.2.2.tgz?cache=0&sync_timestamp=1606424914143&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbabel-loader%2Fdownload%2Fbabel-loader-8.2.2.tgz",
@@ -2412,6 +2441,27 @@
         "object.assign": "^4.1.0"
       }
     },
+    "babel-runtime": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npm.taobao.org/babel-runtime/download/babel-runtime-6.26.0.tgz",
+      "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+      "requires": {
+        "core-js": "^2.4.0",
+        "regenerator-runtime": "^0.11.0"
+      },
+      "dependencies": {
+        "core-js": {
+          "version": "2.6.12",
+          "resolved": "https://registry.npm.taobao.org/core-js/download/core-js-2.6.12.tgz?cache=0&sync_timestamp=1611040756909&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcore-js%2Fdownload%2Fcore-js-2.6.12.tgz",
+          "integrity": "sha1-2TM9+nsGXjR8xWgiGdb2kIWcwuw="
+        },
+        "regenerator-runtime": {
+          "version": "0.11.1",
+          "resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.11.1.tgz?cache=0&sync_timestamp=1595456117883&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerator-runtime%2Fdownload%2Fregenerator-runtime-0.11.1.tgz",
+          "integrity": "sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk="
+        }
+      }
+    },
     "balanced-match": {
       "version": "1.0.0",
       "resolved": "https://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz",
@@ -3686,6 +3736,11 @@
         }
       }
     },
+    "core-js-pure": {
+      "version": "3.8.3",
+      "resolved": "https://registry.npm.taobao.org/core-js-pure/download/core-js-pure-3.8.3.tgz?cache=0&sync_timestamp=1611038562092&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcore-js-pure%2Fdownload%2Fcore-js-pure-3.8.3.tgz",
+      "integrity": "sha1-EOnjslkuyu3kKD6POtcCCBFYfAI="
+    },
     "core-util-is": {
       "version": "1.0.2",
       "resolved": "https://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz",
@@ -4067,8 +4122,7 @@
     "deepmerge": {
       "version": "1.5.2",
       "resolved": "https://registry.npm.taobao.org/deepmerge/download/deepmerge-1.5.2.tgz?cache=0&sync_timestamp=1572279556265&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdeepmerge%2Fdownload%2Fdeepmerge-1.5.2.tgz",
-      "integrity": "sha1-EEmdhohEza1P7ghC34x/bwyVp1M=",
-      "dev": true
+      "integrity": "sha1-EEmdhohEza1P7ghC34x/bwyVp1M="
     },
     "default-gateway": {
       "version": "5.0.5",
@@ -4515,6 +4569,19 @@
       "integrity": "sha1-lGXYhNYJrP/RMbpxCW3nv6vWNnA=",
       "dev": true
     },
+    "element-ui": {
+      "version": "2.15.0",
+      "resolved": "https://registry.npm.taobao.org/element-ui/download/element-ui-2.15.0.tgz?cache=0&sync_timestamp=1610710781355&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Felement-ui%2Fdownload%2Felement-ui-2.15.0.tgz",
+      "integrity": "sha1-3ptzqNHj47UOgrkjpfqVKVI5vUE=",
+      "requires": {
+        "async-validator": "~1.8.1",
+        "babel-helper-vue-jsx-merge-props": "^2.0.0",
+        "deepmerge": "^1.2.0",
+        "normalize-wheel": "^1.0.1",
+        "resize-observer-polyfill": "^1.5.0",
+        "throttle-debounce": "^1.0.1"
+      }
+    },
     "elliptic": {
       "version": "6.5.4",
       "resolved": "https://registry.npm.taobao.org/elliptic/download/elliptic-6.5.4.tgz",
@@ -5425,8 +5492,7 @@
     "follow-redirects": {
       "version": "1.13.2",
       "resolved": "https://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.13.2.tgz",
-      "integrity": "sha1-3XPI7/wScoulz0JZ12DqX7g+MUc=",
-      "dev": true
+      "integrity": "sha1-3XPI7/wScoulz0JZ12DqX7g+MUc="
     },
     "for-in": {
       "version": "1.0.2",
@@ -7054,8 +7120,7 @@
     "lodash": {
       "version": "4.17.20",
       "resolved": "https://registry.npm.taobao.org/lodash/download/lodash-4.17.20.tgz?cache=0&sync_timestamp=1597336147792&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.20.tgz",
-      "integrity": "sha1-tEqbYpe8tpjxxRo1RaKzs2jVnFI=",
-      "dev": true
+      "integrity": "sha1-tEqbYpe8tpjxxRo1RaKzs2jVnFI="
     },
     "lodash.defaultsdeep": {
       "version": "4.6.1",
@@ -7451,6 +7516,11 @@
         "minimist": "^1.2.5"
       }
     },
+    "monent": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npm.taobao.org/monent/download/monent-2.0.0.tgz",
+      "integrity": "sha1-9yG+8yGyHeGMoZTldwrd5YN7txI="
+    },
     "move-concurrently": {
       "version": "1.0.1",
       "resolved": "https://registry.npm.taobao.org/move-concurrently/download/move-concurrently-1.0.1.tgz",
@@ -7504,6 +7574,14 @@
         "thenify-all": "^1.0.0"
       }
     },
+    "naf-core": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npm.taobao.org/naf-core/download/naf-core-0.1.2.tgz",
+      "integrity": "sha1-0UetT3+BTsnSvYGPWCOVHgWAsJU=",
+      "requires": {
+        "lodash": "^4.17.11"
+      }
+    },
     "nan": {
       "version": "2.14.2",
       "resolved": "https://registry.npm.taobao.org/nan/download/nan-2.14.2.tgz?cache=0&sync_timestamp=1602591642885&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnan%2Fdownload%2Fnan-2.14.2.tgz",
@@ -7662,6 +7740,11 @@
       "integrity": "sha1-suHE3E98bVd0PfczpPWXjRhlBVk=",
       "dev": true
     },
+    "normalize-wheel": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npm.taobao.org/normalize-wheel/download/normalize-wheel-1.0.1.tgz",
+      "integrity": "sha1-rsiGr/2wRQcNhWRH32Ls+GFG7EU="
+    },
     "npm-run-path": {
       "version": "2.0.2",
       "resolved": "https://registry.npm.taobao.org/npm-run-path/download/npm-run-path-2.0.2.tgz",
@@ -9109,8 +9192,7 @@
     "regenerator-runtime": {
       "version": "0.13.7",
       "resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.13.7.tgz?cache=0&sync_timestamp=1595456117883&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerator-runtime%2Fdownload%2Fregenerator-runtime-0.13.7.tgz",
-      "integrity": "sha1-ysLazIoepnX+qrrriugziYrkb1U=",
-      "dev": true
+      "integrity": "sha1-ysLazIoepnX+qrrriugziYrkb1U="
     },
     "regenerator-transform": {
       "version": "0.14.5",
@@ -9284,6 +9366,11 @@
       "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
       "dev": true
     },
+    "resize-observer-polyfill": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npm.taobao.org/resize-observer-polyfill/download/resize-observer-polyfill-1.5.1.tgz",
+      "integrity": "sha1-DpAg3T0hAkRY1OvSfiPkAmmBBGQ="
+    },
     "resolve": {
       "version": "1.19.0",
       "resolved": "https://registry.npm.taobao.org/resolve/download/resolve-1.19.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fresolve%2Fdownload%2Fresolve-1.19.0.tgz",
@@ -10460,6 +10547,11 @@
         "neo-async": "^2.6.0"
       }
     },
+    "throttle-debounce": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npm.taobao.org/throttle-debounce/download/throttle-debounce-1.1.0.tgz",
+      "integrity": "sha1-UYU9o3vmihVctugns1FKPEIuic0="
+    },
     "through": {
       "version": "2.3.8",
       "resolved": "https://registry.npm.taobao.org/through/download/through-2.3.8.tgz",
@@ -11134,6 +11226,21 @@
         }
       }
     },
+    "vue-meta": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npm.taobao.org/vue-meta/download/vue-meta-2.4.0.tgz",
+      "integrity": "sha1-pBn7S0E1zpZdqzLsZB0ZicLuSEU=",
+      "requires": {
+        "deepmerge": "^4.2.2"
+      },
+      "dependencies": {
+        "deepmerge": {
+          "version": "4.2.2",
+          "resolved": "https://registry.npm.taobao.org/deepmerge/download/deepmerge-4.2.2.tgz?cache=0&sync_timestamp=1572279556265&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdeepmerge%2Fdownload%2Fdeepmerge-4.2.2.tgz",
+          "integrity": "sha1-RNLqNnm49NT/ujPwPYZfwee/SVU="
+        }
+      }
+    },
     "vue-router": {
       "version": "3.5.1",
       "resolved": "https://registry.npm.taobao.org/vue-router/download/vue-router-3.5.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-router%2Fdownload%2Fvue-router-3.5.1.tgz",
@@ -11178,6 +11285,15 @@
       "resolved": "https://registry.npm.taobao.org/vuex/download/vuex-3.6.2.tgz",
       "integrity": "sha1-I2vAhqhww655lG8QfxbeWdWJXnE="
     },
+    "wangeditor": {
+      "version": "4.6.5",
+      "resolved": "https://registry.npm.taobao.org/wangeditor/download/wangeditor-4.6.5.tgz",
+      "integrity": "sha1-Cj7DkXmOMw2SDFrYzpy30+riO74=",
+      "requires": {
+        "@babel/runtime": "^7.11.2",
+        "@babel/runtime-corejs3": "^7.11.2"
+      }
+    },
     "watchpack": {
       "version": "1.7.5",
       "resolved": "https://registry.npm.taobao.org/watchpack/download/watchpack-1.7.5.tgz?cache=0&sync_timestamp=1607687503110&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwatchpack%2Fdownload%2Fwatchpack-1.7.5.tgz",

+ 8 - 1
package.json

@@ -8,10 +8,17 @@
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
+    "axios": "^0.21.1",
     "core-js": "^3.6.5",
+    "element-ui": "^2.15.0",
+    "lodash": "^4.17.20",
+    "monent": "^2.0.0",
+    "naf-core": "^0.1.2",
     "vue": "^2.6.11",
+    "vue-meta": "^2.4.0",
     "vue-router": "^3.2.0",
-    "vuex": "^3.4.0"
+    "vuex": "^3.4.0",
+    "wangeditor": "^4.6.5"
   },
   "devDependencies": {
     "@vue/cli-plugin-babel": "~4.5.0",

+ 1 - 26
src/App.vue

@@ -1,32 +1,7 @@
 <template>
   <div id="app">
-    <div id="nav">
-      <router-link to="/">Home</router-link> |
-      <router-link to="/about">About</router-link>
-    </div>
     <router-view />
   </div>
 </template>
 
-<style lang="less">
-#app {
-  font-family: Avenir, Helvetica, Arial, sans-serif;
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-  text-align: center;
-  color: #2c3e50;
-}
-
-#nav {
-  padding: 30px;
-
-  a {
-    font-weight: bold;
-    color: #2c3e50;
-
-    &.router-link-exact-active {
-      color: #42b983;
-    }
-  }
-}
-</style>
+<style lang="less"></style>

BIN
src/assets/2.jpg


BIN
src/assets/3.png


BIN
src/assets/achieve.png


BIN
src/assets/bg1.jpg


BIN
src/assets/center/cgxx.png


BIN
src/assets/center/gqxx.png


BIN
src/assets/center/jlhd.png


BIN
src/assets/center/sjdt.png


BIN
src/assets/center/xqxx.png


BIN
src/assets/cha.png


BIN
src/assets/directBack.png


BIN
src/assets/dynamic/1.png


BIN
src/assets/dynamic/2.png


BIN
src/assets/dynamic/3.png


BIN
src/assets/dynamic/4.png


BIN
src/assets/emotion/flower.gif


BIN
src/assets/emotion/flower2.gif


BIN
src/assets/emotion/hand.gif


BIN
src/assets/emotion/touxiang.png


BIN
src/assets/erweima.jpg


BIN
src/assets/expert.png


BIN
src/assets/fmzl.jpg


BIN
src/assets/fmzl1.jpg


BIN
src/assets/hall.jpg


BIN
src/assets/kjpd.png


BIN
src/assets/kjzx.jpg


BIN
src/assets/live/222.png


BIN
src/assets/live/d10_fbb1.png


BIN
src/assets/live/dock_top.png


BIN
src/assets/live/free-qrcode.jpg


BIN
src/assets/live/logo.png


BIN
src/assets/live/main1.png


BIN
src/assets/live/menu_back.jpg


BIN
src/assets/live/square_big.png


BIN
src/assets/live/top_bg.png


BIN
src/assets/login.jpg


BIN
src/assets/logo.png


BIN
src/assets/personal.jpg


BIN
src/assets/personalLive.jpg


BIN
src/assets/product.png


BIN
src/assets/square_big.png


BIN
src/assets/sx.png


BIN
src/assets/techolchat/fb.png


BIN
src/assets/techolchat/jy.png


BIN
src/assets/techolchat/lbyx.png


BIN
src/assets/techolchat/wsdc.png


BIN
src/assets/techolchat/zhfw.png


BIN
src/assets/techolchat/zxzx.png


BIN
src/assets/top_bg.png


BIN
src/assets/train.jpg


BIN
src/assets/video1.mp4


BIN
src/assets/video2.mp4


BIN
src/assets/技术成果1.png


+ 0 - 130
src/components/HelloWorld.vue

@@ -1,130 +0,0 @@
-<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-vuex"
-          target="_blank"
-          rel="noopener"
-          >vuex</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>

+ 60 - 0
src/components/common/foot.vue

@@ -0,0 +1,60 @@
+<template>
+  <div id="foot">
+    <el-row>
+      <el-col :span="24" class="main">
+        <div class="w_1200">
+          <p>
+            <span>技术运营:吉林省科技大市场专利分市场</span>
+          </p>
+          <p>
+            <span>技术支持:长春福瑞科技有限公司</span>
+          </p>
+          <p>
+            <span>地址:吉林省长春市朝阳区前进大街1244号</span>
+            <span>电话:17319450324</span>
+            <span>微信:guhongwei324</span>
+            <span>邮箱:guhongwei0324@163.com</span>
+          </p>
+          <p>
+            <span>吉ICP备2020007658号-1 Copyright 2019 版权所有 中科院长春分院 吉林省计算中心 All Rights Reserved</span>
+          </p>
+        </div>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'foot',
+  props: {},
+  components: {},
+  data: function() {
+    return {};
+  },
+  created() {},
+  methods: {},
+  computed: {},
+  watch: {},
+};
+</script>
+
+<style lang="less" scoped>
+.w_1200 {
+  width: 1200px;
+  margin: 0 auto;
+}
+.main {
+  min-height: 130px;
+  background: #3a3637;
+  p {
+    font-size: 14px;
+    color: #999;
+    font-family: 微软雅黑;
+    padding: 6px 0;
+    span {
+      padding: 0 15px 0 0;
+    }
+  }
+}
+</style>

+ 42 - 0
src/components/common/frame.vue

@@ -0,0 +1,42 @@
+<template>
+  <div id="frame">
+    <el-row>
+      <el-col :span="24" class="frame">
+        <el-col :span="24" class="head">
+          <top></top>
+        </el-col>
+        <el-col :span="24" class="main">
+          <router-view></router-view>
+        </el-col>
+        <el-col :span="24" class="foot">
+          <foot></foot>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import top from './top.vue';
+import foot from './foot.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  name: 'frame',
+  props: {},
+  components: { top, foot },
+  data: function() {
+    return {};
+  },
+  created() {},
+  methods: {},
+  computed: {
+    ...mapState(['user']),
+  },
+  watch: {},
+};
+</script>
+
+<style lang="less" scoped></style>

+ 182 - 0
src/components/common/top.vue

@@ -0,0 +1,182 @@
+<template>
+  <div id="top">
+    <el-row>
+      <el-col :span="24" class="foot">
+        <el-col :span="24" class="top">
+          <div class="w_1200">
+            <el-col :span="12" class="left">
+              欢迎来到中科在线(长春)
+            </el-col>
+            <el-col :span="12" class="right">
+              <el-col :span="24" v-if="user ? user.id : ''">
+                <span>{{ user.name }}</span>
+                <el-button type="primary" size="mini" @click="$router.push({ path: '/userCenter' })">个人中心</el-button>
+                <el-button type="danger" size="mini" @click="logout">退出登录</el-button>
+              </el-col>
+              <el-col :span="24" v-else>
+                <el-button type="primary" size="mini" @click="$router.push({ path: '/login' })">平台登录</el-button>
+                <el-button type="primary" size="mini">管理登录</el-button>
+              </el-col>
+            </el-col>
+          </div>
+        </el-col>
+        <el-col :span="24" class="info">
+          <div class="w_1200">
+            <el-image :src="logo" @click="$router.push({ path: '/' })"></el-image>
+            <span @click="$router.push({ path: '/' })">中科在线(长春)</span>
+          </div>
+        </el-col>
+        <el-col :span="24" class="menu">
+          <div class="w_1200">
+            <el-col :span="24" class="menuInfo">
+              <ul>
+                <li :class="isTab('live') ? 'active' : ''">
+                  <a @click="turnTo('live')" target="">直播大厅</a>
+                </li>
+                <li :class="isTab('market') ? 'active' : ''">
+                  <a @click="turnTo('market')" target="">科技超市</a>
+                </li>
+                <li :class="isTab('news') ? 'active' : ''">
+                  <a @click="turnTo('news')" target="">新闻资讯</a>
+                </li>
+                <li :class="isTab('dynamic') ? 'active' : ''">
+                  <a @click="turnTo('dynamic')" target="">数据动态</a>
+                </li>
+                <li :class="isTab('techolchat') ? 'active' : ''">
+                  <a @click="turnTo('techolchat')" target="">技术交流</a>
+                </li>
+              </ul>
+            </el-col>
+          </div>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'top',
+  props: {},
+  components: {},
+  data: function() {
+    return {
+      logo: require('../../assets/logo.png'),
+    };
+  },
+  created() {},
+  methods: {
+    turnTo(type) {
+      this.$router.push({ path: `/${type}/index` });
+    },
+    // 选中
+    isTab(type) {
+      return this.$route.path.includes(`/${type}`);
+    },
+    // 退出登录
+    logout() {
+      localStorage.removeItem('token');
+      localStorage.removeItem('type');
+      this.$router.push('/');
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  watch: {},
+};
+</script>
+
+<style lang="less" scoped>
+.w_1200 {
+  width: 1200px;
+  margin: 0 auto;
+}
+.foot {
+  height: 250px;
+  background: url('../../assets/top_bg.png');
+  background-repeat: no-repeat;
+  background-size: 100% 100%;
+  .top {
+    height: 40px;
+    line-height: 40px;
+    background: #2152991f;
+    .left {
+      color: #fff;
+    }
+    .right {
+      text-align: right;
+      span {
+        display: inline-block;
+        padding: 0px 10px;
+        font-weight: bold;
+      }
+    }
+  }
+  .info {
+    height: 160px;
+    overflow: hidden;
+    position: relative;
+    .el-image {
+      width: 70px;
+      height: 70px;
+      overflow: hidden;
+      top: 40px;
+    }
+    span {
+      color: #2d64b3;
+      font-size: 36px;
+      font-family: cursive;
+      text-shadow: -1px 0 #fff, 0 1px #fff, 1px 0 #fff, 0 -1px #fff;
+      font-weight: 600;
+      padding: 0 10px;
+      position: absolute;
+      height: 160px;
+      line-height: 160px;
+    }
+  }
+  .info:hover {
+    cursor: pointer;
+  }
+  .menu {
+    .menuInfo {
+      height: 50px;
+      overflow: hidden;
+      background: #0085d2;
+      ul {
+        margin: 0;
+        padding: 0;
+        li {
+          float: left;
+          width: 239px;
+          height: 50px;
+          line-height: 50px;
+          list-style: none;
+          text-align: center;
+          font-size: 20px;
+          border-right: 1px solid #f1f1f1;
+          color: #fff;
+          a {
+            float: left;
+            width: 100%;
+            height: 50px;
+            line-height: 50px;
+          }
+        }
+        li:hover {
+          cursor: pointer;
+          background-color: #fe950e;
+        }
+      }
+      ul .active {
+        background-color: #fe950e;
+      }
+      ul li:last-child {
+        width: 240px;
+        border-right: 0;
+      }
+    }
+  }
+}
+</style>

+ 50 - 0
src/components/frame/filter-page-table.md

@@ -0,0 +1,50 @@
+## filter-page-table.vue
+#### prop
+|参数|类型|默认值|是否必填|说明|
+|:-:|:-:|:-:|:-:|:-:|
+|fields|Array|`-`|是|字段列表(下文会说明如何使用)|
+|data|Array|`-`|是|数据列表|
+|opera|Array|[ ]|否|操作列的列表(下文会说明如何使用)|
+|toFormat|Function|`-`|否|如果fields中的format不是function类型,则会走toFormat的方法,需要自己写过滤规则,多个的情况需要区分|
+|select|Boolean|false|否|需要选择就变成true|
+|total|NUmber|0|否|分页的总数据|
+|usePage|Boolean|true|否|是否使用分页|
+|options|Object|null|否|加些属性,不知道能加啥,反正我把合计加上好使了|
+|useSum|Boolean|false|否|使用合计|
+|filter|Array|`[]`|否|额外查询|
+|operaWidth|Number|200|否|操作栏宽度|
+
+>fields
+>>
+|参数|类型|默认值|是否必填|说明|
+|:-:|:-:|:-:|:-:|:-:|
+|label|String|`-`|是|列名称|
+|prop|String|`-`|是|字段名称|
+|format|Function/String|`-`|否|Function类型:数据需要过滤则将过滤方法写在这;String类型:走toFormat方法,参数位(model=>字段名,value=>值)|
+|custom|Boolean|false|否|自定义输出|
+|options|Object|`-`|否|添加额外属性,比如说样式之类的|
+|filter|String|`-`|否|如果填写,则这个字段会查询,这里只填写类型,input/select,select的选项在options插槽中使用|
+|selected|Array|`-`|false|多选选项的数据|
+|showTip|Boolean|false|否|是否使用tooltip显示过长内容|
+|filterReturn|Boolean|`-`|否|针对这个选项需要在选择后就做些逻辑处理时,改成true,然后再使用filterReturn方法处理,(例如二级联动的情况)|
+|notable|Boolean|false/undefined|否|不需要在表格中显示|
+|selected|Array|`-`|false|多选选项的数据|
+
+>opera
+>>
+|参数|类型|默认值|是否必填|说明|
+|:-:|:-:|:-:|:-:|:-:|
+|label|String|`-`|是|操作按钮提示文字|
+|icon|String|`-`|否|图标|
+|method|String|`-`|是|此按钮连接的父级方法($emit)|
+|confirm|Boolean|`-`|否|是否需要确认提示|
+|methodZh|String/Function|label|否|确认提示的操作文字,1,Function参数为这条数据,自己随意组合;2,String为纯自定义字符串,需要自己写整个提示语;3,默认,使用label字段提示|
+|display|Function|`-`|否|控制按钮是否显示(目前为简单版,只是根据此条数据中的内容判断,以后要是有需求会修改成toFormat的形式)|
+
+>methods
+>>
+|方法名|参数|说明|
+|:-:|:-:|:-:|
+|handleSelect|Array[object]|返回选择的内容|
+|query|{skip,limit,...info}|分页查询,及条件查询|
+|filterReturn|{data,prop}|查询条件栏过滤条件中filterReturn字段为true的回调方法|

+ 312 - 0
src/components/frame/filter-page-table.vue

@@ -0,0 +1,312 @@
+<template>
+  <div id="data-table">
+    <el-form :model="searchInfo" :inline="true" style="padding:0.9rem 1.875rem ;" size="mini" v-if="useFilter">
+      <el-form-item v-for="(item, index) in filterList" :key="index">
+        <template v-if="item.filter === 'select'">
+          <el-select
+            v-model="searchInfo[item.prop]"
+            size="mini"
+            clearable
+            filterable
+            :placeholder="`请选择${item.label}`"
+            @clear="toClear(item.prop)"
+            @change="data => filterReturn(data, item)"
+          >
+            <slot name="options" v-bind="{ item }"></slot>
+          </el-select>
+        </template>
+        <template v-else-if="item.filter === 'date'">
+          <el-date-picker
+            v-model="searchInfo[item.prop]"
+            value-format="yyyy-MM-dd"
+            format="yyyy-MM-dd"
+            type="daterange"
+            range-separator="-"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            clearable
+          >
+          </el-date-picker>
+        </template>
+        <template v-else>
+          <el-input v-model="searchInfo[item.prop]" clearable size="mini" :placeholder="`请输入${item.label}`" @clear="toClear(item.prop)"></el-input>
+        </template>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" size="mini" @click="filterSearch">查询</el-button>
+      </el-form-item>
+    </el-form>
+    <el-table
+      ref="table"
+      row-key="id"
+      :data="data"
+      border
+      stripe
+      size="mini"
+      :max-height="height !== null ? height : ''"
+      @select="handleSelectionChange"
+      @select-all="handleSelectAll"
+      v-bind="options"
+      :show-summary="useSum"
+      @row-click="rowClick"
+    >
+      <el-table-column type="selection" width="55" v-if="select" prop="id" :reserve-selection="true"> </el-table-column>
+      <template v-for="(item, index) in fields">
+        <template v-if="!item.notable">
+          <template v-if="item.custom">
+            <el-table-column :key="index" align="center" :label="item.label" v-bind="item.options">
+              <template v-slot="{ row }">
+                <slot name="custom" v-bind="{ item, row }"></slot>
+              </template>
+            </el-table-column>
+          </template>
+          <template v-else>
+            <el-table-column
+              :key="index"
+              align="center"
+              :label="item.label"
+              :prop="item.prop"
+              :formatter="toFormatter"
+              sortable
+              v-bind="item.options"
+              :show-overflow-tooltip="item.showTip || true"
+            >
+            </el-table-column>
+          </template>
+        </template>
+      </template>
+      <template v-if="opera.length > 0">
+        <el-table-column label="操作" align="center" :width="operaWidth">
+          <template v-slot="{ row, $index }">
+            <template v-for="(item, index) in opera">
+              <template v-if="display(item, row)">
+                <el-tooltip v-if="item.icon" :key="index" effect="dark" :content="item.label" placement="bottom">
+                  <el-button
+                    :key="index"
+                    type="text"
+                    :icon="item.icon || ''"
+                    size="mini"
+                    @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index)"
+                  ></el-button>
+                </el-tooltip>
+                <!-- <el-button v-else :key="index" type="text" size="mini" @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index)">
+                  {{ item.label }}
+                </el-button> -->
+                <el-link
+                  v-else
+                  :key="`${item.model}-column-${index}`"
+                  :type="item.type || 'primary'"
+                  :icon="item.icon || ''"
+                  size="mini"
+                  style="padding-right:10px"
+                  :underline="false"
+                  @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index)"
+                >
+                  {{ item.label }}
+                </el-link>
+              </template>
+            </template>
+          </template>
+        </el-table-column>
+      </template>
+    </el-table>
+    <el-row type="flex" align="middle" justify="end" style="padding-top:1rem" v-if="usePage">
+      <el-col :span="24" style="text-align:right;">
+        <el-pagination
+          background
+          layout="total, prev, pager, next"
+          :page-sizes="[10, 15, 20, 50, 100]"
+          :total="total"
+          :page-size="limit"
+          :current-page.sync="currentPage"
+          @current-change="changePage"
+          @size-change="sizeChange"
+        >
+        </el-pagination>
+        <!-- sizes -->
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import _ from 'lodash';
+export default {
+  name: 'data-table',
+  props: {
+    fields: { type: Array, required: true },
+    data: { type: Array, required: true },
+    opera: { type: Array, default: () => [] },
+    toFormat: null,
+    height: null,
+    select: { type: Boolean, default: false },
+    selected: { type: Array, default: () => [] },
+    usePage: { type: Boolean, default: true },
+    total: { type: Number, default: 0 },
+    options: null,
+    useSum: { type: Boolean, default: false },
+    filter: { type: Array, default: () => [] },
+    operaWidth: { type: Number, default: 200 },
+    limit: { type: Number, default: _.get(this, `$limit`, undefined) !== undefined ? this.$limit : process.env.VUE_APP_LIMIT * 1 || 10 },
+  },
+  components: {},
+  data: () => ({
+    pageSelected: [],
+    currentPage: 1,
+    // limit: _.get(this, `$limit`, undefined) !== undefined ? this.$limit : process.env.VUE_APP_LIMIT * 1 || 10,
+    searchInfo: {},
+    useFilter: true,
+    filterList: [],
+  }),
+  created() {},
+  computed: {},
+  methods: {
+    toFormatter(row, column, cellValue, index) {
+      let this_fields = this.fields.filter(fil => fil.prop === column.property);
+      if (this_fields.length > 0) {
+        let format = _.get(this_fields[0], `format`, false);
+        if (format) {
+          let res;
+          if (_.isFunction(format)) {
+            res = format(cellValue);
+          } else {
+            res = this.toFormat({
+              model: this_fields[0].prop,
+              value: cellValue,
+            });
+          }
+          return res;
+        } else return cellValue;
+      }
+    },
+    handleOpera(data, method, confirm = false, methodZh, label, index) {
+      let self = true;
+      if (_.isFunction(methodZh)) {
+        methodZh = methodZh(data);
+      } else if (!_.isString(methodZh)) {
+        methodZh = label;
+        self = false;
+      }
+      if (confirm) {
+        this.$confirm(self ? methodZh : `您确认${methodZh}该数据?`, '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning',
+        })
+          .then(() => {
+            this.$emit(method, { data, index });
+          })
+          .catch(() => {});
+      } else {
+        this.$emit(method, { data, index });
+      }
+    },
+    handleSelectionChange(selection, row) {
+      // console.log(selection);
+      // console.log(row);
+      //根据row是否再pageSelected中,判断是添加还是删除
+      let res = [];
+      if (this.pageSelected.find(i => i.id === row.id)) {
+        res = this.pageSelected.filter(f => f.id !== row.id);
+      } else {
+        this.pageSelected.push(row);
+        res = this.pageSelected;
+      }
+      this.$set(this, `pageSelected`, res);
+      this.$emit(`handleSelect`, _.uniqBy(res, 'id'));
+    },
+    handleSelectAll(selection) {
+      //处于没全选状态,选择之后一定是全选,只有处于全选状态时,才会反选(全取消)
+      // console.log(selection);
+      let res = [];
+      if (selection.length > 0) {
+        //全选
+        res = _.uniqBy(this.pageSelected.concat(selection), 'id');
+      } else {
+        //全取消
+        res = _.differenceBy(this.pageSelected, this.data, 'id');
+      }
+      this.$set(this, `pageSelected`, res);
+      this.$emit(`handleSelect`, res);
+    },
+    initSelection() {
+      this.$nextTick(() => {
+        this.$refs.table.clearSelection();
+        this.selected.forEach(info => {
+          let d = this.data.filter(p => p.id === info.id);
+          if (d.length > 0) this.$refs.table.toggleRowSelection(d[0]);
+        });
+      });
+    },
+    selectReset() {
+      this.$refs.table.clearSelection();
+    },
+    display(item, row) {
+      let display = _.get(item, `display`, true);
+      if (display === true) return true;
+      else {
+        let res = display(row);
+        return res;
+      }
+    },
+    //
+    changePage(page = this.currentPage) {
+      this.$emit('query', { skip: (page - 1) * this.limit, limit: this.limit, ...this.searchInfo });
+    },
+    sizeChange(limit) {
+      this.limit = limit;
+      this.currentPage = 1;
+      this.$emit('query', { skip: 0, limit: this.limit, ...this.searchInfo });
+    },
+    getFilterList() {
+      let res = this.fields.filter(f => _.get(f, 'filter', false));
+      this.$set(this, `useFilter`, res.length > 0);
+      res.map(i => {
+        if (i.filter === 'date' && this.searchInfo[i.porp] === undefined) this.$set(this.searchInfo, i.prop, []);
+      });
+      res = [...res, ...this.filter];
+      this.$set(this, `filterList`, res);
+    },
+    filterSearch() {
+      this.currentPage = 1;
+      this.$emit('query', { skip: 0, limit: this.limit, ...this.searchInfo });
+    },
+    rowClick(row, column, event) {
+      this.$emit(`rowClick`, row);
+    },
+    toClear(prop) {
+      delete this.searchInfo[prop];
+    },
+    filterReturn(data, item) {
+      let { prop, filterReturn } = item;
+      if (filterReturn) this.$emit('filterReturn', { data, prop });
+    },
+  },
+  watch: {
+    selected: {
+      handler(val) {
+        if (val.length > 0) {
+          this.pageSelected = val;
+          this.initSelection();
+        }
+      },
+      immediate: true,
+    },
+    data: {
+      handler(val, oval) {
+        if (this.select) {
+          this.initSelection();
+        }
+      },
+    },
+    fields: {
+      handler(val, oval) {
+        if (val) this.getFilterList();
+      },
+      immediate: true,
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 82 - 0
src/components/frame/form.md

@@ -0,0 +1,82 @@
+# 组件说明文档
+### form.vue
+### props
+
+|参数|类型|默认值|是否必填|说明|
+|:-:|:-:|:-:|:-:|:-:|
+|fields|Array|`-`|是|字段相关都在这里,用来自动输出,详情见下面|
+|submitText|String|`保存`|否|默认保存按钮的文字|
+|rules|Object|`-`|否|校验规则,不会找el-form的例子,不过使用的async-validator这个依赖为基础,会写这个也可以~~(那就厉害了,反正我是不行)~~|
+|isNew|Boolean|`-`|是|修改还是添加的提示|
+|data|Object|`-`|否|修改传来的数据|
+|needSave|Boolean|false|否|是否禁用保存按钮|
+|useEnter|Boolean|true|否|使用回车提交|
+|reset|Boolean|true|否|提交后是否重置表单|
+
+
+### fields
+>Array类型 必填
+>>
+|参数|类型|默认值|是否必填|说明|
+|:-:|:-:|:-:|:-:|:-:|
+|label|String|`-`|是|显示的字段中文|
+|type|String|input|否|这个字段要用什么类型来输出 input的基本类型可选值:date,datetime,radio,checkbox,select,text(只显示值),editor(富文本编辑器),password|
+|required|Boolean|`-`|否|是否必须输入|
+|model|String|`-`|是|字段名|
+|placeholder|String|`-`|否|占位,正常用,只是个透传|
+|options|object|`-`|否|标签的属性设置,例如:textarea 需要显示剩余字数,或者input限制长度,都往这里写,key-value形式(键值对,json的基本了解,不知道百度,具体属性看你具体用那个组件,那个组件有什么属性,瞎写不一定好使)|
+|custom|Boolean|`-`|否|是否使用自定义插槽|
+|tip|String|`-`|否|提示语,例如:请输入11位电话号码|
+|labelWidth|String|`120px`|否|表单label宽度,element的,默认120px|
+|format|Function|`-`|否|当type = text 时需要将该字段内容转换,可以使用format|
+
+
+
+
+
+
+
+### slot
+>
+|插槽名|说明|
+|:-:|:-:|
+|options|fields中type为select的,选项都写在这个插槽中,多个select则需要区分options所属问题|
+|radios|fields中type为radio的,选项都写在这个插槽中,多个radio则需要区分radios所属问题|
+|checkbox|fields中type为checkbox的,选项都写在这个插槽中,多个checkbox则需要区分checkboxs所属问题|
+|custom|自定义插槽,完全自己去写|
+|submit|提交按钮部分,当needSave为false时才可以使用|
+>>关于自定义的用法:
+>>在fields中,custom:true的情况即需要自定义,写法如下
+
+>>`<template #custom="{ item, form, fieldChange }"> ... </template>`
+>>
+|参数名|说明|
+|:-:|:-:|
+|item|fields循环出来的每一项|
+|form|组件内部的表单|
+|fieldChange|组件内部的修改方法,此方法不一定必须使用,看情况来;参数:{model:xxx,value:XXX}(model:字段名,value:值)|
+>>在使用时,此插槽内的v-model可以写成form[item.model],也可以写成form.字段名
+
+>>例如`<el-input v-model="form[item.model]">`或者`<el-input v-model="form.xxx">`
+
+>> **如果有多处需要自定义,请区分开去写**
+
+
+***
+### upload
+|参数|类型|默认值|是否必填|说明|
+|:-:|:-:|:-:|:-:|:-:|
+|url|String|`-`|是|上传地址|
+|limit|Number|`-`|是|限制上传数量|
+|data|any|`-`|否|上传数据|
+|type|String|`-`|否|上传返回的字段|
+|isBtn|Boolean|false|否|是否只显示按钮|
+|showList|Boolean|true|否|是否显示上传列表|
+|accept|String|`-`|否|可以上传的文件类型,不写就没限制|
+|tip|String|`-`|否|提示信息|
+|listType|String|picture-card|否|上传文件列表显示类型|
+
+>### method
+>|方法名|返回参数|说明|
+|:-:|:-:|:-:|
+|upload|{type,data}|上传成功返回

+ 211 - 0
src/components/frame/form.vue

@@ -0,0 +1,211 @@
+<template>
+  <div id="add">
+    <el-form
+      ref="form"
+      :model="form"
+      :rules="rules"
+      :label-width="labelWidth"
+      class="form"
+      size="small"
+      @submit.native.prevent
+      :style="styles"
+      :inline="inline"
+    >
+      <template v-for="(item, index) in fields">
+        <template v-if="!loading">
+          <el-form-item v-if="display(item)" :key="'form-field-' + index" :label="getField('label', item)" :prop="item.model" :required="item.required">
+            <template v-if="!item.custom">
+              <template v-if="item.type !== 'text'">
+                <el-tooltip class="item" effect="dark" :content="item.tip" placement="top-start" :disabled="!item.tip">
+                  <template v-if="item.type === `date` || item.type === `datetime`">
+                    <el-date-picker
+                      v-model="form[item.model]"
+                      :type="item.type"
+                      placeholder="选择择"
+                      format="yyyy-MM-dd"
+                      value-format="yyyy-MM-dd"
+                      v-bind="item.options"
+                    >
+                    </el-date-picker>
+                  </template>
+                  <template v-else-if="item.type === `year` || item.type === `week` || item.type === `day`">
+                    <el-date-picker
+                      v-model="form[item.model]"
+                      :type="item.type"
+                      placeholder="选择择"
+                      :format="`${item.type === 'year' ? 'yyyy' : item.type === 'week' ? 'MM' : 'dd'}`"
+                      :value-format="`${item.type === 'year' ? 'yyyy' : item.type === 'week' ? 'MM' : 'dd'}`"
+                      v-bind="item.options"
+                    >
+                    </el-date-picker>
+                  </template>
+                  <template v-else-if="item.type === 'time'">
+                    <el-time-picker v-model="form[item.model]" placeholder="请选择时间" format="HH:mm" value-format="HH:mm"></el-time-picker>
+                  </template>
+                  <template v-else-if="item.type === 'radio'">
+                    <el-radio-group v-model="form[item.model]" size="mini" v-bind="item.options">
+                      <slot name="radios" v-bind="{ item, form, fieldChange }"></slot>
+                    </el-radio-group>
+                  </template>
+                  <template v-else-if="item.type === 'checkbox'">
+                    <el-checkbox-group v-model="form[item.model]" v-bind="item.options">
+                      <slot name="checkboxs" v-bind="{ item, form, fieldChange }"></slot>
+                    </el-checkbox-group>
+                  </template>
+                  <template v-else-if="item.type === 'select'">
+                    <el-select v-model="form[item.model]" v-bind="item.options" filterable clearable>
+                      <slot name="options" v-bind="{ item, form, fieldChange }"></slot>
+                    </el-select>
+                  </template>
+                  <template v-else-if="item.type === 'textarea'">
+                    <el-input clearable v-model="form[item.model]" type="textarea" :autosize="{ minRows: 3, maxRows: 5 }"></el-input>
+                  </template>
+                  <template v-else-if="item.type === 'editor'">
+                    <wang-editor v-model="form[item.model]"></wang-editor>
+                  </template>
+                  <template v-else>
+                    <el-input
+                      clearable
+                      v-model="form[item.model]"
+                      :type="getField('type', item)"
+                      :placeholder="getField('placeholder', item)"
+                      :show-password="getField('type', item) === 'password'"
+                      v-bind="item.options"
+                    ></el-input>
+                  </template>
+                </el-tooltip>
+              </template>
+              <template v-else>
+                <template v-if="item.format">
+                  {{ item.format(form[item.model]) }}
+                </template>
+                <template v-else>
+                  {{ form[item.model] }}
+                </template>
+              </template>
+            </template>
+            <template v-else>
+              <slot name="custom" v-bind="{ item, form, fieldChange }"></slot>
+            </template>
+          </el-form-item>
+        </template>
+      </template>
+      <el-form-item label="" v-if="needSave" class="btn">
+        <el-row type="flex" align="middle" justify="start">
+          <el-col :span="6">
+            <el-button type="primary" @click="save">{{ submitText }}</el-button>
+          </el-col>
+        </el-row>
+      </el-form-item>
+      <el-form-item v-else>
+        <slot name="submit"></slot>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import _ from 'lodash';
+import wangEditor from './wang-editor.vue';
+export default {
+  name: 'add',
+  props: {
+    fields: { type: Array, default: () => [] },
+    rules: { type: Object, default: () => {} },
+    isNew: { type: Boolean, default: true },
+    data: null,
+    styles: { type: Object, default: () => {} },
+    needSave: { type: Boolean, default: true },
+    labelWidth: { type: String, default: '120px' },
+    useEnter: { type: Boolean, default: true },
+    submitText: { type: String, default: '保存' },
+    inline: { type: Boolean, default: false },
+    reset: { type: Boolean, default: true },
+  },
+  components: {
+    wangEditor,
+  },
+  data: () => ({
+    form: {},
+    show: false,
+    dateShow: false,
+    loading: true,
+  }),
+  created() {
+    if (this.useEnter) {
+      document.onkeydown = () => {
+        let key = window.event.keyCode;
+        if (key == 13) {
+          this.save();
+        }
+      };
+    }
+  },
+  computed: {},
+  mounted() {},
+  watch: {
+    fields: {
+      handler(val) {
+        this.checkType();
+      },
+      immediate: true,
+    },
+    data: {
+      handler(val) {
+        this.loading = true;
+        if (val) this.$set(this, `form`, this.data);
+        this.loading = false;
+      },
+      immediate: true,
+      deep: true,
+    },
+  },
+  methods: {
+    getField(item, data) {
+      let res = _.get(data, item, null);
+      if (item === 'type') res = res === null ? `text` : res;
+      if (item === 'placeholder') res = res === null ? `请输入${data.label}` : res;
+      if (item === 'required') res = res === null ? false : res;
+      if (item === `error`) res = res === null ? `${data.label}错误` : res;
+      return res;
+    },
+    save() {
+      this.$refs['form'].validate(valid => {
+        if (valid) {
+          this.$emit(`save`, { isNew: this.isNew, data: JSON.parse(JSON.stringify(this.form)) });
+          if (this.reset) this.$refs.form.resetFields();
+        } else {
+          console.warn('form validate error!!!');
+        }
+      });
+    },
+    fieldChange({ model, value }) {
+      this.$set(this.form, model, value);
+    },
+    checkType() {
+      let arr = this.fields.filter(fil => fil.type === 'checkbox');
+      if (arr.length > 0 && this.isNew) {
+        for (const item of arr) {
+          this.$set(this.form, `${item.model}`, []);
+        }
+      }
+    },
+    display(field) {
+      let dis = _.get(field, `display`);
+      if (!_.isFunction(dis)) return true;
+      else return dis(field, this.form);
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.form {
+  padding: 2rem 1rem;
+  background: #fff;
+  border-radius: 20px;
+}
+// /deep/.btn .el-form-item__content {
+//   margin-left: 0 !important;
+// }
+</style>

+ 11 - 0
src/components/frame/pagination.md

@@ -0,0 +1,11 @@
+# pagination.vue 分页组件
+#### props
+|参数|类型|默认值|是否必填|说明|
+|:-:|:-:|:-:|:-:|:-:|
+|position|String|'right'|否|组件的布局位置,默认为靠右侧|
+|total|Number|0|是|分页的总数据数,用来计算页码|
+|limit|Number|10|否|每页的数量|  
+#### methods
+|方法名|参数|说明|
+|:-:|:-:|:-:|
+|query|{skip,limit,...info}|分页查询|

+ 51 - 0
src/components/frame/pagination.vue

@@ -0,0 +1,51 @@
+<template>
+  <div id="pagination">
+    <el-row type="flex" align="middle" style="padding-top:1rem">
+      <el-col :span="24" :style="`text-align:${position};`">
+        <el-pagination
+          background
+          layout=" total, prev, pager, next"
+          :total="total"
+          :page-size="limit"
+          :current-page.sync="currentPage"
+          @current-change="changePage"
+        >
+        </el-pagination>
+        <!-- 
+          :page-sizes="[5, 10, 15, 20, 50, 100]"
+          @size-change="sizeChange"
+         -->
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import _ from 'lodash';
+export default {
+  name: 'pagination',
+  props: {
+    position: { type: String, default: 'right' },
+    total: { type: Number, default: 0 },
+    limit: { type: Number, default: 10 },
+  },
+  components: {},
+  data: () => {
+    return {
+      currentPage: 1,
+    };
+  },
+  created() {},
+  methods: {
+    changePage(page) {
+      this.$emit('query', { skip: (page - 1) * this.limit, limit: this.limit });
+    },
+    sizeChange(limit) {
+      this.limit = limit;
+      this.$emit('query', { skip: 0, limit: this.limit });
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 172 - 0
src/components/frame/swiper-frame.md

@@ -0,0 +1,172 @@
+# 组件文档说明
+
+## 下载依赖
+### npm install vue-awesome-swiper  --save
+### npm install swiper@5.3.6  --save
+
+## options设置
+### 1
+切换效果 fade cube coverflow flip
+effect: 'flip',
+样式设定
+fadeEffect: {
+淡出fade
+crossFade: true,
+方块切换 cube
+slideShadows: true,
+shadow: true,
+shadowOffset: 100,
+shadowScale: 0.6,
+coverflow
+slidesPerView: 3,
+centeredSlides: true,
+coverflowEffect: {
+  rotate: 30,
+  stretch: 10,
+  depth: 60,
+  modifier: 2,
+  slideShadows: true,
+},
+flip
+slideShadows: true,
+limitRotation: true,
+},
+### 2
+不可拖动文字
+noSwiping: true,
+### 3
+当你的Swiper在过渡时将无法滑动
+preventInteractionOnTransition : true,
+短切换,长切花
+shortSwipes: false,
+自由滑动,不知道滑过几个
+freeMode: true,
+### 4
+设置预览值 px
+slidesOffsetBefore: 100,
+显示多行
+slidesPerView: 3, //一行显示3个
+slidesPerColumn: 2, //显示2行
+### 5
+一页显示三个,一组为三个
+slidesPerView: 3,
+slidesPerGroup: 3,
+### 6
+slidesPerView: 2,
+//slidesPerView : 'auto',    根据slide的宽度自动调整展示数量。此时需要设置slide的宽度,如下style所示
+//slidesPerView : 3.7,
+### 7
+默认居中,并一页显示三个,第一条在左侧
+slidesPerView: 3,
+centeredSlides: true,
+centeredSlidesBounds: true,
+### 8
+默认居中,并一页显示三个,第一个在中间
+slidesPerView: 3,
+centeredSlides: true,
+### 9
+如果有一个数据时,所有分页,按钮,分页点全部失效
+watchOverflow: true,
+### 10
+滑过触发回调
+runCallbacksOnInit: true,
+on: {
+  slideChangeTransitionStart: function() {
+    选中值
+    console.log(this.activeIndex);
+  },
+},
+### 11
+自适应高度 随silde变化而变化
+autoHeight: true,
+### 12
+默认一页显示数
+slidesPerView: 4,
+数据间隔 px
+spaceBetween: 30,
+不同屏幕配置
+breakpoints: {
+  320: {
+    //当屏幕宽度大于等于320
+    slidesPerView: 2,
+    spaceBetween: 10,
+  },
+  768: {
+    //当屏幕宽度大于等于768
+    slidesPerView: 3,
+    spaceBetween: 20,
+  },
+  1280: {
+    //当屏幕宽度大于等于1280
+    slidesPerView: 4,
+    spaceBetween: 30,
+  },
+},
+### 13
+鼠标滑过显示小手
+grabCursor: true,
+### 14
+自动滑过贴合时间
+speed: 300,
+autoplay: {
+  默认3秒切换一次
+  delay: 3000,
+到最后一个自动停止
+stopOnLastSlide: true,
+触碰当前页自动停止
+disableOnInteraction: true,
+反向自动轮播
+reverseDirection: true,
+},
+### 15
+自动滑过
+autoplay: true,
+//鼠标覆盖停止自动切换
+### 16
+默认索引值,0:开始
+initialSlide: 0,
+### 17
+垂直切换选项
+direction: 'vertical',
+### 18
+循环轮播
+loop: true,
+### 19
+分页
+pagination: {
+el: '.swiper-pagination',
+clickable为true时,点击小点控制轮播
+clickable: true,
+分页类型
+type: 'bullets',//点
+type: 'fraction',//数字
+type: 'progressbar',//上条
+type: 'custom', //自定义
+progressbarOpposite: true,//progressbar-左条
+bulletElement: 'li',//指定标签
+dynamicBullets: true,//bullets-点数过多,隐藏
+dynamicMainBullets: 4,//显示点数量
+hideOnClick: true,//点击数据时,隐藏分页
+自定义点样式
+renderBullet: function(index, className) {
+  return '<span class="' + className + '">' + (index + 1) + '</span>';
+},
+设置分式
+type: 'fraction',
+renderFraction: function(currentClass, totalClass) {
+  return '<span class="' + currentClass + '"></span>' + ' of ' + '<span class="' + totalClass + '"></span>';
+},
+自定义点样式
+type: 'custom',
+renderCustom: function(swiper, current, total) {
+  return current + ' of ' + total;
+},
+bulletClass: 'my-bullet', //需设置.my-bullet样式
+bulletActiveClass: 'my-bullet-active', //需设置my-bullet-active样式
+},
+### 20
+按钮导航
+navigation: {
+  nextEl: '.swiper-button-next',
+  prevEl: '.swiper-button-prev',
+},

+ 64 - 0
src/components/frame/swiper-frame.vue

@@ -0,0 +1,64 @@
+<template>
+  <div id="swiper-frame">
+    <div class="container">
+      <div class="swiper-box">
+        <swiper ref="mySwiper" :options="options">
+          <swiper-slide v-for="(item, index) in list" :key="index">
+            <slot v-bind="{ index, item }"></slot>
+          </swiper-slide>
+          <!-- 分页 -->
+          <div class="swiper-pagination" slot="pagination"></div>
+          <!-- 按钮导航 -->
+          <div class="swiper-button-prev" slot="button-prev"></div>
+          <div class="swiper-button-next" slot="button-next"></div>
+        </swiper>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { Swiper, SwiperSlide } from 'vue-awesome-swiper';
+import 'swiper/css/swiper.css';
+export default {
+  name: 'swiper-frame',
+  props: {
+    // 循环列表
+    list: { type: Array, default: () => [] },
+    // 配置文件
+    options: { type: Object, default: () => {} },
+  },
+  components: { Swiper, SwiperSlide },
+  data: function() {
+    return {};
+  },
+  created() {},
+  methods: {},
+  computed: {},
+  watch: {},
+};
+</script>
+
+<style lang="less" scoped>
+.swiper-box {
+  .swiper-container {
+    height: 45px;
+  }
+}
+// 选中背景颜色,字颜色
+// .swiper-slide-active {
+//   background: #ff6600;
+//   color: #fff;
+// }
+// 设定固定值
+// .swiper-slide {
+//   width: 300px; /*设为固定值*/
+//   width: auto; /*根据内容调整宽度*/
+// }
+// 自定义按钮样式
+// .swiper-container {
+//   --swiper-theme-color: #ff6600; /* 设置Swiper风格 */
+//   --swiper-navigation-color: #00ff33; /* 单独设置按钮颜色 */
+//   --swiper-navigation-size: 30px; /* 设置按钮大小 */
+// }
+</style>

+ 120 - 0
src/components/frame/upload.vue

@@ -0,0 +1,120 @@
+<template>
+  <div id="upload">
+    <el-upload
+      v-if="url"
+      ref="upload"
+      :action="url"
+      :list-type="listType"
+      :file-list="fileList"
+      :limit="limit"
+      :on-exceed="outLimit"
+      :on-preview="handlePictureCardPreview"
+      :before-remove="handleRemove"
+      :on-success="onSuccess"
+      :before-upload="beforeUpload"
+      :show-file-list="showList"
+      :accept="accept"
+    >
+      <el-button size="small" type="primary" v-if="isBtn">点击上传</el-button>
+      <template v-else-if="uploadBtn">
+        <el-button type="danger">选择文件</el-button>
+      </template>
+      <template v-else>
+        <el-button type="primary" size="mini">选择文件</el-button>
+      </template>
+      <template #tip v-if="tip">
+        {{ tip }}
+      </template>
+    </el-upload>
+    <el-dialog :visible.sync="dialogVisible">
+      <img width="100%" :src="dialogImageUrl" alt="" />
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import _ from 'lodash';
+export default {
+  name: 'upload',
+  props: {
+    url: { type: null },
+    limit: { type: Number },
+    data: { type: null },
+    type: { type: String },
+    isBtn: { type: Boolean, default: false },
+    uploadBtn: { type: Boolean, default: false },
+    showList: { type: Boolean, default: true },
+    accept: { type: String, default: '' },
+    tip: { type: String, default: undefined },
+    listType: { type: String, default: 'picture-card' },
+  },
+  components: {},
+  data: () => ({
+    dialogVisible: false,
+    dialogImageUrl: '',
+    fileList: [],
+  }),
+  created() {
+    if (this.data) {
+      this.defalutProcess(this.data);
+    }
+  },
+  watch: {
+    data: {
+      handler(val) {
+        this.defalutProcess(val);
+      },
+    },
+  },
+  computed: {},
+  methods: {
+    handlePictureCardPreview(file) {
+      this.dialogImageUrl = file.url;
+      this.dialogVisible = false;
+    },
+    handleRemove(file, fileList) {
+      this.$set(this, `fileList`, []);
+      // let index = fileList.findIndex(f => _.isEqual(f, file));
+      this.$emit('delete', { file, type: this.type });
+      return false;
+    },
+    outLimit() {
+      this.$message.error(`只允许上传${this.limit}个文件`);
+    },
+    onSuccess(response, file, fileList) {
+      //将文件整理好传回父组件
+      this.$emit('upload', { type: this.type, data: { ...response, name: file.name } });
+    },
+    beforeUpload(file) {
+      const sizeLimit = file.size / 1024 / 1024 < 100;
+      if (sizeLimit) return true;
+      else {
+        this.$message.error('文件超出10M!');
+        return false;
+      }
+    },
+    defalutProcess(val) {
+      if (_.isArray(val)) {
+        let newArr = val.map(item => {
+          let object = {};
+          object.name = item.name;
+          object.url = item.url;
+          return object;
+        });
+        this.$set(this, `fileList`, newArr);
+      } else if (_.isObject(val)) {
+        let object = {};
+        if (_.get(val, `url`)) {
+          object.name = val.name;
+          object.url = val.url;
+          this.$set(this, `fileList`, [object]);
+        }
+      } else if (typeof val === 'string') {
+        this.$set(this, `fileList`, [{ name: '附件', url: val }]);
+      }
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 264 - 0
src/components/frame/vform.vue

@@ -0,0 +1,264 @@
+<template>
+  <div id="add">
+    <el-form ref="form" :model="form" :label-width="labelWidth" class="form" size="small" @submit.native.prevent :style="styles" :inline="inline">
+      <template v-for="(item, index) in fields">
+        <el-form-item
+          v-if="display(item)"
+          :key="'form-field-' + index"
+          :label="getField('label', item)"
+          :prop="item.model"
+          :required="item.required"
+          :rules="getRules(item)"
+        >
+          <template v-if="!item.custom">
+            <template v-if="item.type !== 'text'">
+              <el-tooltip class="item" effect="dark" :content="item.remark" placement="top-start" :disabled="!item.remark">
+                <template v-if="item.type === `date` || item.type === `datetime`">
+                  <el-date-picker
+                    v-model="form[item.model]"
+                    :type="item.type"
+                    placeholder="选择择"
+                    :format="`yyyy-MM-dd${item.type == 'datetime' ? ' HH:mm:ss' : ''}`"
+                    :value-format="`yyyy-MM-dd${item.type == 'datetime' ? ' HH:mm:ss' : ''}`"
+                    v-bind="item.options"
+                  >
+                  </el-date-picker>
+                </template>
+                <template v-else-if="item.type === `year` || item.type === `week` || item.type === `day`">
+                  <el-date-picker
+                    v-model="form[item.model]"
+                    :type="item.type"
+                    placeholder="选择择"
+                    :format="`${item.type === 'year' ? 'yyyy' : item.type === 'week' ? 'MM' : 'dd'}`"
+                    :value-format="`${item.type === 'year' ? 'yyyy' : item.type === 'week' ? 'MM' : 'dd'}`"
+                    v-bind="item.options"
+                  >
+                  </el-date-picker>
+                </template>
+                <template v-else-if="item.type === 'number'">
+                  <el-input-number v-model="form[item.model]" placeholder="" controls-position="right" style="width:200px"></el-input-number>
+                </template>
+                <template v-else-if="item.type === 'time'">
+                  <el-time-picker v-model="form[item.model]" placeholder="请选择时间" format="HH:mm" value-format="HH:mm"></el-time-picker>
+                </template>
+                <template v-else-if="item.type === 'radio'">
+                  <el-radio-group v-model="form[item.model]" size="mini" v-bind="item.options">
+                    <template v-if="item.list">
+                      <el-radio v-for="(i, iIndex) in item.list" :key="`radio-${iIndex}`" :label="i.value">{{ i.label }}</el-radio>
+                    </template>
+                    <template v-else>
+                      <slot name="radios" v-bind="{ item, form, fieldChange }"></slot>
+                    </template>
+                  </el-radio-group>
+                </template>
+                <template v-else-if="item.type === 'checkbox'">
+                  <el-checkbox-group v-model="form[item.model]" v-bind="item.options">
+                    <template v-if="item.list">
+                      <el-checkbox v-for="(i, iIndex) in item.list" :key="`checkbox-${iIndex}`" :label="i.value">{{ i.label }}</el-checkbox>
+                    </template>
+                    <template v-else>
+                      <slot name="checkboxs" v-bind="{ item, form, fieldChange }"></slot>
+                    </template>
+                  </el-checkbox-group>
+                </template>
+                <template v-else-if="item.type === 'select'">
+                  <el-select
+                    v-model="form[item.model]"
+                    v-bind="item.options"
+                    filterable
+                    clearable
+                    @change="data => filterReturn(data, item)"
+                    default-first-option
+                  >
+                    <template v-if="item.list">
+                      <el-option v-for="(i, iIndex) in item.list" :key="`checkbox-${iIndex}`" :label="i.label" :value="i.value"></el-option>
+                    </template>
+                    <template v-else>
+                      <slot name="options" v-bind="{ item, form, fieldChange }"> </slot>
+                    </template>
+                  </el-select>
+                </template>
+                <template v-else-if="item.type === 'textarea'">
+                  <el-input clearable v-model="form[item.model]" type="textarea" :autosize="{ minRows: 3, maxRows: 5 }"></el-input>
+                </template>
+                <template v-else-if="item.type === 'editor'">
+                  <wang-editor v-model="form[item.model]"></wang-editor>
+                </template>
+                <template v-else>
+                  <el-input
+                    clearable
+                    v-model="form[item.model]"
+                    :type="getField('type', item)"
+                    :placeholder="getField('placeholder', item)"
+                    :show-password="getField('type', item) === 'password'"
+                    v-bind="item.options"
+                  ></el-input>
+                </template>
+              </el-tooltip>
+            </template>
+            <template v-else>
+              <template v-if="item.format">
+                {{ item.format(form[item.model]) }}
+              </template>
+              <template v-else>
+                {{ form[item.model] }}
+              </template>
+            </template>
+          </template>
+          <template v-else>
+            <slot name="custom" v-bind="{ item, form, fieldChange }"></slot>
+          </template>
+        </el-form-item>
+      </template>
+      <el-form-item label="" v-if="needSave" class="btn">
+        <el-row type="flex" align="middle" justify="start">
+          <el-col :span="6">
+            <el-button type="primary" @click="save">{{ submitText }}</el-button>
+          </el-col>
+        </el-row>
+      </el-form-item>
+      <el-form-item v-else>
+        <slot name="submit"></slot>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import _ from 'lodash';
+import wangEditor from '@common/src/components/frame/wang-editor.vue';
+export default {
+  name: 'vform',
+  model: {
+    prop: 'form',
+    event: 'change',
+  },
+  props: {
+    fields: { type: Array, default: () => [] },
+    rules: { type: Object, default: () => ({}) },
+    isNew: { type: Boolean, default: true },
+    form: { type: Object, default: () => {} },
+    styles: { type: Object, default: () => {} },
+    needSave: { type: Boolean, default: true },
+    labelWidth: { type: String, default: '120px' },
+    useEnter: { type: Boolean, default: true },
+    submitText: { type: String, default: '保存' },
+    inline: { type: Boolean, default: false },
+    reset: { type: Boolean, default: true },
+  },
+  components: {
+    wangEditor,
+  },
+  data: () => {
+    // form: {},
+    const _this = this;
+    return {
+      show: false,
+      dateShow: false,
+    };
+  },
+  created() {
+    if (this.useEnter) {
+      document.onkeydown = () => {
+        let key = window.event.keyCode;
+        if (key == 13) {
+          this.save();
+        }
+      };
+    }
+  },
+  computed: {},
+  mounted() {},
+  watch: {
+    fields: {
+      handler(val) {
+        this.checkType();
+      },
+      immediate: true,
+      deep: true,
+    },
+  },
+  methods: {
+    getField(item, data) {
+      let res = _.get(data, item, null);
+      if (item === 'type') res = res === null ? `text` : res;
+      if (item === 'placeholder') res = res === null ? `请输入${data.label}` : res;
+      if (item === 'required') res = res === null ? false : res;
+      if (item === `error`) res = res === null ? `${data.label}错误` : res;
+      return res;
+    },
+    save() {
+      this.$refs['form'].validate(valid => {
+        if (valid) {
+          this.$emit(`save`, { isNew: this.isNew, data: JSON.parse(JSON.stringify(this.form)) });
+          if (this.reset) this.$refs.form.resetFields();
+        } else {
+          console.warn('form validate error!!!');
+        }
+      });
+    },
+    fieldChange({ model, value }) {
+      this.$set(this.form, model, value);
+    },
+    //
+    checkType() {
+      let arr = this.fields.filter(fil => fil.type === 'checkbox');
+      if (arr.length > 0 && this.isNew) {
+        for (const item of arr) {
+          this.$set(this.form, `${item.model}`, []);
+        }
+      }
+    },
+    getRules(data) {
+      let rules = [];
+      const { model, required, label } = data;
+      if (this.rules && _.get(this.rules, model)) {
+        const r = _.get(this.rules, model);
+        let has_required = false;
+        if (_.isArray(r)) {
+          for (const rule of r) {
+            if (_.get(rule, 'required')) {
+              has_required = true;
+              break;
+            }
+          }
+          rules = r;
+        } else {
+          if (_.get(rule, 'required')) has_required = true;
+          rules.push(r);
+        }
+        if (!has_required) rules.push({ required: true, message: `请填写${label}`, trigger: 'blur' });
+      } else {
+        if (required) {
+          let obj = { required: true, message: `请填写${label}`, trigger: 'blur' };
+          rules.push(obj);
+        }
+      }
+      return rules;
+    },
+    display(field) {
+      // 添加noform属性,与列表fields共用
+      let noform = _.get(field, `noform`);
+      if (noform) return false;
+      let dis = _.get(field, `display`);
+      if (!_.isFunction(dis)) return true;
+      else return dis(field, this.form);
+    },
+    filterReturn(data, item) {
+      let { model, filterReturn } = item;
+      if (filterReturn) this.$emit('filterReturn', { data, model });
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.form {
+  padding: 1.5rem 1rem;
+  background: #fff;
+  border-radius: 20px;
+}
+// /deep/.btn .el-form-item__content {
+//   margin-left: 0 !important;
+// }
+</style>

+ 77 - 0
src/components/frame/wang-editor.vue

@@ -0,0 +1,77 @@
+<template>
+  <div ref="editor" style="text-align:left"></div>
+</template>
+<script>
+import E from 'wangeditor';
+
+const menus = [
+  'head', // 标题
+  'bold', // 粗体
+  'fontSize', // 字号
+  'fontName', // 字体
+  'italic', // 斜体
+  'underline', // 下划线
+  'strikeThrough', // 删除线
+  'foreColor', // 文字颜色
+  'backColor', // 背景颜色
+  'link', // 插入链接
+  'list', // 列表
+  'justify', // 对齐方式
+  'quote', // 引用
+  // 'emoticon', // 表情
+  'table', // 表格
+  // 'video', // 插入视频
+  // 'code', // 插入代码
+  'undo', // 撤销
+  'redo', // 重复
+];
+
+export default {
+  name: 'wang-editor',
+  model: {
+    prop: 'value',
+    event: 'change', // 默认为input时间,此处改为change
+  },
+  props: {
+    value: { type: String, required: false, default: '' },
+  },
+  data() {
+    return {
+      editorContent: this.value,
+    };
+  },
+  mounted() {
+    var editor = new E(this.$refs.editor);
+    editor.customConfig.onchange = html => {
+      this.editorContent = html;
+      this.$emit('change', html);
+    };
+    // 自定义菜单配置
+    editor.customConfig.menus = menus;
+    editor.customConfig.zIndex = 0;
+    editor.customConfig.uploadImgServer = '/files/cms/images/upload';
+    editor.customConfig.uploadImgMaxLength = 1;
+    editor.customConfig.uploadImgHooks = {
+      // 如果服务器端返回的不是 {errno:0, data: [...]} 这种格式,可使用该配置
+      // (但是,服务器端返回的必须是一个 JSON 格式字符串!!!否则会报错)
+      customInsert: function(insertImg, result, editor) {
+        // 图片上传并返回结果,自定义插入图片的事件(而不是编辑器自动插入图片!!!)
+        // insertImg 是插入图片的函数,editor 是编辑器对象,result 是服务器端返回的结果
+
+        // 举例:假如上传图片成功后,服务器端返回的是 {url:'....'} 这种格式,即可这样插入图片:
+        var url = result.uri;
+        insertImg(url);
+
+        // result 必须是一个 JSON 格式字符串!!!否则报错
+      },
+    };
+    editor.create();
+    editor.txt.html(this.value);
+  },
+  methods: {
+    getContent: function() {
+      return this.editorContent;
+    },
+  },
+};
+</script>

+ 119 - 0
src/components/upload/uploadArray.vue

@@ -0,0 +1,119 @@
+<template>
+  <div id="upload">
+    <el-upload
+      v-if="url"
+      ref="upload"
+      :action="url"
+      :list-type="listType"
+      :file-list="fileList"
+      :limit="limit"
+      :on-exceed="outLimit"
+      :on-preview="handlePictureCardPreview"
+      :before-remove="handleRemove"
+      :on-success="onSuccess"
+      :before-upload="beforeUpload"
+      :show-file-list="showList"
+      :accept="accept"
+    >
+      <el-button size="small" type="primary" v-if="isBtn">点击上传</el-button>
+      <template v-else-if="uploadBtn">
+        <el-button type="danger">选择文件</el-button>
+      </template>
+      <template v-else>
+        <el-button type="primary" size="mini">选择文件</el-button>
+      </template>
+      <template #tip v-if="tip">
+        {{ tip }}
+      </template>
+    </el-upload>
+    <el-dialog :visible.sync="dialogVisible">
+      <img width="100%" :src="dialogImageUrl" alt="" />
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import _ from 'lodash';
+export default {
+  name: 'upload',
+  props: {
+    url: { type: null },
+    limit: { type: Number },
+    data: { type: null },
+    type: { type: String },
+    isBtn: { type: Boolean, default: false },
+    uploadBtn: { type: Boolean, default: false },
+    showList: { type: Boolean, default: true },
+    accept: { type: String, default: '' },
+    tip: { type: String, default: undefined },
+    listType: { type: String, default: 'picture-card' },
+  },
+  components: {},
+  data: () => ({
+    dialogVisible: false,
+    dialogImageUrl: '',
+    fileList: [],
+  }),
+  created() {
+    if (this.data) {
+      this.defalutProcess(this.data);
+    }
+  },
+  watch: {
+    data: {
+      handler(val) {
+        this.defalutProcess(val);
+      },
+    },
+  },
+  computed: {},
+  methods: {
+    handlePictureCardPreview(file) {
+      this.dialogImageUrl = file.url;
+      this.dialogVisible = false;
+    },
+    handleRemove(file, fileList) {
+      let index = fileList.findIndex(f => _.isEqual(f, file));
+      this.$emit('delete', index);
+      return false;
+    },
+    outLimit() {
+      this.$message.error(`只允许上传${this.limit}个文件`);
+    },
+    onSuccess(response, file, fileList) {
+      //将文件整理好传回父组件
+      this.$emit('upload', { type: this.type, data: { ...response, name: file.name } });
+    },
+    beforeUpload(file) {
+      const sizeLimit = file.size / 1024 / 1024 < 10;
+      if (sizeLimit) return true;
+      else {
+        this.$message.error('文件超出10M!');
+        return false;
+      }
+    },
+    defalutProcess(val) {
+      if (_.isArray(val)) {
+        let newArr = val.map(item => {
+          let object = {};
+          object.name = item.name;
+          object.url = item.url;
+          return object;
+        });
+        this.$set(this, `fileList`, newArr);
+      } else if (_.isObject(val)) {
+        let object = {};
+        if (_.get(val, `url`)) {
+          object.name = val.name;
+          object.url = val.url;
+          this.$set(this, `fileList`, [object]);
+        }
+      } else if (typeof val === 'string') {
+        this.$set(this, `fileList`, [{ name: '附件', url: val }]);
+      }
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 6 - 6
src/main.js

@@ -1,12 +1,12 @@
-import Vue from "vue";
-import App from "./App.vue";
-import router from "./router";
-import store from "./store";
+import Vue from 'vue';
+import App from './App.vue';
+import router from './router';
+import store from './store';
 
 Vue.config.productionTip = false;
 
 new Vue({
   router,
   store,
-  render: h => h(App)
-}).$mount("#app");
+  render: h => h(App),
+}).$mount('#app');

+ 2 - 14
src/router/index.js

@@ -7,24 +7,12 @@ Vue.use(VueRouter);
 const routes = [
   {
     path: "/",
-    name: "Home",
-    component: Home
+    component: () => import("../views/index.vue"),
   },
-  {
-    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({
-  mode: "history",
-  base: process.env.BASE_URL,
-  routes
+  routes,
 });
 
 export default router;

+ 38 - 0
src/store/category.js

@@ -0,0 +1,38 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+Vue.use(Vuex);
+const api = {
+  interface: `/api/live/v0/system/category`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit = 10, ...info } = {}) {
+    const res = await this.$axios.$get(api.interface, { skip, limit, ...info });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.interface}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.interface}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...info } = {}) {
+    const res = await this.$axios.$post(`${api.interface}/${id}`, { ...info });
+    return res;
+  },
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.interface}/${payload}`);
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 53 - 0
src/store/channel.js

@@ -0,0 +1,53 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+const jwt = require('jsonwebtoken');
+Vue.use(Vuex);
+const api = {
+  channelInfo: `/api/live/v0/dock/channel`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.channelInfo}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.channelInfo}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.channelInfo}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.channelInfo}/update/${id}`, data);
+    return res;
+  },
+
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.channelInfo}/${payload}`);
+    return res;
+  },
+  async login({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.channelInfo}/login`, payload);
+    if (res.errcode === 0) {
+      localStorage.setItem('token', res.data);
+      const user = jwt.decode(res.data);
+      commit('setUser', user, { root: true });
+    }
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 53 - 0
src/store/channelVideo.js

@@ -0,0 +1,53 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+const jwt = require('jsonwebtoken');
+Vue.use(Vuex);
+const api = {
+  channelInfo: `/api/live/v0/dock/channelVideo`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.channelInfo}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.channelInfo}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.channelInfo}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.channelInfo}/update/${id}`, data);
+    return res;
+  },
+
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.channelInfo}/${payload}`);
+    return res;
+  },
+  async login({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.channelInfo}/login`, payload);
+    if (res.errcode === 0) {
+      localStorage.setItem('token', res.data);
+      const user = jwt.decode(res.data);
+      commit('setUser', user, { root: true });
+    }
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 40 - 0
src/store/code.js

@@ -0,0 +1,40 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+Vue.use(Vuex);
+const api = {
+  interface: `/api/live/v0/system/code`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(api.interface, { skip, limit, ...info });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.interface}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.interface}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...info } = {}) {
+    const res = await this.$axios.$post(`${api.interface}/update/${id}`, {
+      ...info,
+    });
+    return res;
+  },
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.interface}/${payload}`);
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 43 - 0
src/store/column.js

@@ -0,0 +1,43 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+Vue.use(Vuex);
+const api = {
+  columnInfo: `/api/live/v0/tecinfo/column`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.columnInfo}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.columnInfo}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.columnInfo}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.columnInfo}/update/${id}`, data);
+    return res;
+  },
+
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.columnInfo}/${payload}`);
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 63 - 0
src/store/dock.js

@@ -0,0 +1,63 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+const jwt = require('jsonwebtoken');
+Vue.use(Vuex);
+const api = {
+  dockInfo: `/site/api/live/v0/dock/index`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.dockInfo}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.dockInfo}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.dockInfo}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.dockInfo}/update/${id}`, data);
+    return res;
+  },
+
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.dockInfo}/${payload}`);
+    return res;
+  },
+
+  async login({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.dockInfo}/login`, payload);
+    if (res.errcode === 0) {
+      localStorage.setItem('token', res.data);
+      const user = jwt.decode(res.data);
+      commit('setUser', user, { root: true });
+    }
+    return res;
+  },
+  // 查询展会产品
+  async productQuery({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.dockInfo}/product`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 44 - 0
src/store/dockPw.js

@@ -0,0 +1,44 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+const jwt = require('jsonwebtoken');
+Vue.use(Vuex);
+const api = {
+  dockInfo: `/site/api/live/v0/dock/dockPw`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.dockInfo}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.dockInfo}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.dockInfo}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.dockInfo}/update/${id}`, data);
+    return res;
+  },
+
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.dockInfo}/${payload}`);
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 62 - 0
src/store/dockUser.js

@@ -0,0 +1,62 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+Vue.use(Vuex);
+const api = {
+  dockUserInfo: `/api/live/v0/dock/dockUser`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.dockUserInfo}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.dockUserInfo}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.dockUserInfo}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.dockUserInfo}/update/${id}`, data);
+    return res;
+  },
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.dockUserInfo}/${payload}`);
+    return res;
+  },
+  async dockUser({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.dockUserInfo}/find`, {
+      skip,
+      limit,
+      ...info,
+    });
+  },
+
+  /**
+   * 审核产品
+   * @param {Object} {commit} vuex参数
+   * @param {Object} {id,status} 产品参数
+   * @property {String} id 用户id
+   * @property {String} status 产品状态
+   * @property {String} good_id 用户选择的产品的id(也是正常在产品表里的id,这里id直接用没有重新生成)
+   */
+  async goodsCheck({ commit }, { id, good_id, status }) {
+    const res = await this.$axios.$post(`${api.dockUserInfo}/check/goods/${id}`, { good_id, status });
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 57 - 0
src/store/expert.js

@@ -0,0 +1,57 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+const jwt = require('jsonwebtoken');
+Vue.use(Vuex);
+const api = {
+  expertInfo: `/api/live/v0/users/expert`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.expertInfo}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.expertInfo}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.expertInfo}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.expertInfo}/update/${id}`, data);
+    return res;
+  },
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.expertInfo}/${payload}`);
+    return res;
+  },
+  // 修改密码
+  async updatePassword({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.expertInfo}/password/${id}`, data);
+    return res;
+  },
+  async expLogin({ commit }, { user }) {
+    const res = await this.$axios.$post(`${api.expertInfo}/login`, user);
+    if (res.errcode === 0) {
+      localStorage.setItem('token', res.data);
+      user = jwt.decode(res.data);
+      commit('setUser', user, { root: true });
+    }
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 0 - 11
src/store/index.js

@@ -1,11 +0,0 @@
-import Vue from "vue";
-import Vuex from "vuex";
-
-Vue.use(Vuex);
-
-export default new Vuex.Store({
-  state: {},
-  mutations: {},
-  actions: {},
-  modules: {}
-});

+ 43 - 0
src/store/interview.js

@@ -0,0 +1,43 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+Vue.use(Vuex);
+const api = {
+  interviewInfo: `/api/live/v0/dock/interview`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.interviewInfo}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.interviewInfo}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.interviewInfo}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.interviewInfo}/update/${id}`, data);
+    return res;
+  },
+
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.interviewInfo}/${payload}`);
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 26 - 0
src/store/inviteCode.js

@@ -0,0 +1,26 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+Vue.use(Vuex);
+const api = {
+  inviteCodeInfo: `/api/live/v0/system/inviteCode`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.inviteCodeInfo}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 43 - 0
src/store/menu.js

@@ -0,0 +1,43 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+Vue.use(Vuex);
+const api = {
+  menuInfo: `/api/live/v0/system/menu`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.menuInfo}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.menuInfo}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.menuInfo}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.menuInfo}/update/${id}`, data);
+    return res;
+  },
+
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.menuInfo}/${payload}`);
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 43 - 0
src/store/news.js

@@ -0,0 +1,43 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+Vue.use(Vuex);
+const api = {
+  newsInfo: `/api/live/v0/tecinfo/news`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.newsInfo}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.newsInfo}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.newsInfo}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.newsInfo}/update/${id}`, data);
+    return res;
+  },
+
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.newsInfo}/${payload}`);
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 43 - 0
src/store/notice.js

@@ -0,0 +1,43 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+Vue.use(Vuex);
+const api = {
+  noticeInfo: `/api/live/v0/system/notice`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.noticeInfo}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.noticeInfo}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.noticeInfo}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.noticeInfo}/update/${id}`, data);
+    return res;
+  },
+
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.noticeInfo}/${payload}`);
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 57 - 0
src/store/organization.js

@@ -0,0 +1,57 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+const jwt = require('jsonwebtoken');
+Vue.use(Vuex);
+const api = {
+  organizationInfo: `/api/live/v0/users/organization`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.organizationInfo}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.organizationInfo}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.organizationInfo}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.organizationInfo}/update/${id}`, data);
+    return res;
+  },
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.organizationInfo}/${payload}`);
+    return res;
+  },
+  // 修改密码
+  async updatePassword({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.organizationInfo}/password/${id}`, data);
+    return res;
+  },
+  async orgLogin({ commit }, { user }) {
+    const res = await this.$axios.$post(`${api.organizationInfo}/login`, user);
+    if (res.errcode === 0) {
+      localStorage.setItem('token', res.data);
+      user = jwt.decode(res.data);
+      commit('setUser', user, { root: true });
+    }
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 43 - 0
src/store/patent.js

@@ -0,0 +1,43 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+Vue.use(Vuex);
+const api = {
+  patentInfo: `/api/live/v0/dock/patent`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.patentInfo}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.patentInfo}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.patentInfo}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.patentInfo}/update/${id}`, data);
+    return res;
+  },
+
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.patentInfo}/${payload}`);
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 61 - 0
src/store/personal.js

@@ -0,0 +1,61 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+const jwt = require('jsonwebtoken');
+Vue.use(Vuex);
+const api = {
+  personalInfo: `/api/live/v0/users/personal`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.personalInfo}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.personalInfo}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.personalInfo}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.personalInfo}/update/${id}`, data);
+    return res;
+  },
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.personalInfo}/${payload}`);
+    return res;
+  },
+  // 修改密码
+  async updatePassword({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.personalInfo}/password/${id}`, data);
+    return res;
+  },
+  async perLogin({ commit }, { user }) {
+    const res = await this.$axios.$post(`${api.personalInfo}/login`, user);
+    if (res.errcode === 0) {
+      localStorage.setItem('token', res.data);
+      user = jwt.decode(res.data);
+      commit('setUser', user, { root: true });
+    }
+    return res;
+  },
+  async upgradeUser({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.personalInfo}/upgrade`, payload);
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 43 - 0
src/store/place.js

@@ -0,0 +1,43 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+Vue.use(Vuex);
+const api = {
+  placeInfo: `/api/live/v0/system/code`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.placeInfo}/xzqh`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async queryName({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.placeInfo}/name`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.placeInfo}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.placeInfo}/update/${id}`, data);
+    return res;
+  },
+
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.placeInfo}/${payload}`);
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 43 - 0
src/store/product.js

@@ -0,0 +1,43 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+Vue.use(Vuex);
+const api = {
+  productInfo: `/api/live/v0/users/product`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.productInfo}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.productInfo}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.productInfo}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.productInfo}/update/${id}`, data);
+    return res;
+  },
+
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.productInfo}/${payload}`);
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 43 - 0
src/store/roadShow.js

@@ -0,0 +1,43 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+Vue.use(Vuex);
+const api = {
+  roadShowInfo: `/api/live/v0/dock/roadShow`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.roadShowInfo}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.roadShowInfo}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.roadShowInfo}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.roadShowInfo}/update/${id}`, data);
+    return res;
+  },
+
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.roadShowInfo}/${payload}`);
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 43 - 0
src/store/science.js

@@ -0,0 +1,43 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+Vue.use(Vuex);
+const api = {
+  scienceInfo: `/api/live/v0/tecinfo/science`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.scienceInfo}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.scienceInfo}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.scienceInfo}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...data }) {
+    const res = await this.$axios.$post(`${api.scienceInfo}/update/${id}`, data);
+    return res;
+  },
+
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.scienceInfo}/${payload}`);
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 22 - 0
src/store/statistics.js

@@ -0,0 +1,22 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+Vue.use(Vuex);
+const api = {
+  interface: `/api/live/v0/statistics/index`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, key) {
+    const res = await this.$axios.$get(`${api.interface}/${key}`);
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 0 - 0
src/store/survey.js


Some files were not shown because too many files changed in this diff