rindy 6 éve
commit
5a294c1151
81 módosított fájl, 15518 hozzáadás és 0 törlés
  1. 3 0
      .browserslistrc
  2. 9 0
      .editorconfig
  3. 1 0
      .env
  4. 1 0
      .env.production
  5. 21 0
      .gitignore
  6. 10 0
      .jsbeautifyrc
  7. 29 0
      README.md
  8. 15 0
      babel.config.js
  9. 10729 0
      package-lock.json
  10. 35 0
      package.json
  11. 5 0
      postcss.config.js
  12. BIN
      public/favicon.ico
  13. 28 0
      public/index.html
  14. BIN
      public/static/banner/1.jpg
  15. BIN
      public/static/img/bg-bottom-right.png
  16. BIN
      public/static/img/bg-home.png
  17. BIN
      public/static/img/bg-top-left.png
  18. BIN
      public/static/img/bg-upload.png
  19. BIN
      public/static/img/bg-upload1.png
  20. BIN
      public/static/img/icons/check.png
  21. BIN
      public/static/img/icons/clear.png
  22. BIN
      public/static/img/icons/keyboard-active.png
  23. BIN
      public/static/img/icons/keyboard.png
  24. BIN
      public/static/img/icons/list-active.png
  25. BIN
      public/static/img/icons/list.png
  26. BIN
      public/static/img/icons/upload-active.png
  27. BIN
      public/static/img/icons/upload.png
  28. BIN
      public/static/img/icons/write-active.png
  29. BIN
      public/static/img/icons/write.png
  30. BIN
      public/static/img/loading.gif
  31. BIN
      public/static/img/test.png
  32. BIN
      public/static/img/touch-save.png
  33. 1 0
      public/static/lib/flexible.min.js
  34. 6 0
      public/static/lib/html2canvas.min.js
  35. 2 0
      public/static/lib/jroll.2.6.5.min.js
  36. 12 0
      public/static/lib/swiper-4.3.5.min.css
  37. 13 0
      public/static/lib/swiper-4.3.5.min.js
  38. 4 0
      public/static/worker.comments.js
  39. 14 0
      src/App.vue
  40. BIN
      src/assets/images/logo.png
  41. BIN
      src/assets/images/心情墙.png
  42. 357 0
      src/assets/styles/_base.less
  43. 5 0
      src/assets/styles/_variables.less
  44. 372 0
      src/assets/styles/global.css
  45. 64 0
      src/assets/styles/global.less
  46. 15 0
      src/auth.js
  47. 116 0
      src/components/BackToTop/index.vue
  48. 43 0
      src/components/SvgIcon/index.vue
  49. 365 0
      src/config/fonts.js
  50. 9 0
      src/icons/index.js
  51. 1 0
      src/icons/svg/colors.svg
  52. 1 0
      src/icons/svg/fonts.svg
  53. 40 0
      src/icons/svg/keyboard.svg
  54. 30 0
      src/icons/svg/select.svg
  55. 30 0
      src/icons/svg/upload.svg
  56. 30 0
      src/icons/svg/write.svg
  57. 22 0
      src/icons/svgo.yml
  58. 22 0
      src/main.js
  59. 35 0
      src/plugins.js
  60. 44 0
      src/router.js
  61. 16 0
      src/store.js
  62. 3 0
      src/utils/bus.js
  63. 16 0
      src/utils/http.js
  64. 52 0
      src/views/Auth/index.vue
  65. 64 0
      src/views/Cart/index.vue
  66. 289 0
      src/views/Console/components/Comments.vue
  67. 290 0
      src/views/Console/components/FileUpload.vue
  68. 75 0
      src/views/Console/components/Setting.vue
  69. 94 0
      src/views/Console/index.vue
  70. 19 0
      src/views/Error/index.vue
  71. 58 0
      src/views/Fonts/index.vue
  72. 71 0
      src/views/Home/components/QrCode.vue
  73. 70 0
      src/views/Home/components/UserDraw.vue
  74. 35 0
      src/views/Home/components/UserText.vue
  75. 396 0
      src/views/Home/index.vue
  76. 16 0
      src/views/Message/components/Tabs.vue
  77. 1189 0
      src/views/Message/index.vue
  78. 42 0
      src/views/Shared/Layout.vue
  79. 33 0
      src/views/Shared/components/Footer.vue
  80. 114 0
      src/views/Shared/components/Header.vue
  81. 37 0
      vue.config.js

+ 3 - 0
.browserslistrc

@@ -0,0 +1,3 @@
+> 5%
+last 3 versions
+not ie <= 8

+ 9 - 0
.editorconfig

@@ -0,0 +1,9 @@
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 4
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true

+ 1 - 0
.env

@@ -0,0 +1 @@
+VUE_APP_BASEAPI=http://192.168.0.100:8089

+ 1 - 0
.env.production

@@ -0,0 +1 @@
+VUE_APP_BASEAPI=

+ 21 - 0
.gitignore

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

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 10 - 0
.jsbeautifyrc


+ 29 - 0
README.md

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

+ 15 - 0
babel.config.js

@@ -0,0 +1,15 @@
+module.exports = {
+  presets: [
+    '@vue/app'
+  ],
+  plugins: [
+    [
+      "component",
+      {
+        "libraryName": "element-ui",
+        //"styleLibraryName": "~theme"
+        "styleLibraryName": "theme-chalk"
+      }
+    ]
+  ]
+}

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 10729 - 0
package-lock.json


+ 35 - 0
package.json

@@ -0,0 +1,35 @@
+{
+  "name": "wyd-mail",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "serve": "vue-cli-service serve",
+    "build": "vue-cli-service build",
+    "dev": "npm run serve",
+    "start": "npm run serve",
+    "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml"
+  },
+  "dependencies": {
+    "axios": "^0.18.0",
+    "big.js": "^5.2.2",
+    "element-ui": "^2.4.11",
+    "js-cookie": "^2.2.0",
+    "nprogress": "^0.2.0",
+    "qs": "^6.6.0",
+    "vue": "^2.5.17",
+    "vue-router": "^3.0.1",
+    "vuex": "^3.0.1"
+  },
+  "devDependencies": {
+    "@vue/cli-plugin-babel": "^3.2.0",
+    "@vue/cli-service": "^3.2.0",
+    "babel-plugin-component": "^1.1.1",
+    "less": "^3.0.4",
+    "less-loader": "^4.1.0",
+    "style-resources-loader": "^1.2.1",
+    "svg-sprite-loader": "^4.1.3",
+    "svgo": "^1.1.1",
+    "vue-cli-plugin-style-resources-loader": "^0.1.3",
+    "vue-template-compiler": "^2.5.17"
+  }
+}

+ 5 - 0
postcss.config.js

@@ -0,0 +1,5 @@
+module.exports = {
+  plugins: {
+    autoprefixer: {}
+  }
+}

BIN
public/favicon.ico


+ 28 - 0
public/index.html

@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+    <meta name="renderer" content="webkit" />
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta content="yes" name="apple-mobile-web-app-capable">
+    <meta content="yes" name="apple-touch-fullscreen">
+    <meta content="black" name="apple-mobile-web-app-status-bar-style">
+    <meta content="telephone=no" name="format-detection">
+    <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
+    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+    <link rel="stylesheet" href="static/lib/swiper-4.3.5.min.css" />
+    <title>律道心情墙</title>
+    <script src="static/lib/flexible.min.js" async></script>
+  </head>
+  <body>
+    <noscript>
+      <strong>We're sorry but wyd-mail doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
+    </noscript>
+    <div id="app"></div>
+    <script src="static/lib/swiper-4.3.5.min.js"></script>
+    <script src="static/lib/jroll.2.6.5.min.js"></script>
+    <script src="static/lib/html2canvas.min.js"></script>
+    <!-- built files will be auto injected -->
+  </body>
+</html>

BIN
public/static/banner/1.jpg


BIN
public/static/img/bg-bottom-right.png


BIN
public/static/img/bg-home.png


BIN
public/static/img/bg-top-left.png


BIN
public/static/img/bg-upload.png


BIN
public/static/img/bg-upload1.png


BIN
public/static/img/icons/check.png


BIN
public/static/img/icons/clear.png


BIN
public/static/img/icons/keyboard-active.png


BIN
public/static/img/icons/keyboard.png


BIN
public/static/img/icons/list-active.png


BIN
public/static/img/icons/list.png


BIN
public/static/img/icons/upload-active.png


BIN
public/static/img/icons/upload.png


BIN
public/static/img/icons/write-active.png


BIN
public/static/img/icons/write.png


BIN
public/static/img/loading.gif


BIN
public/static/img/test.png


BIN
public/static/img/touch-save.png


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 0
public/static/lib/flexible.min.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 6 - 0
public/static/lib/html2canvas.min.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 2 - 0
public/static/lib/jroll.2.6.5.min.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 12 - 0
public/static/lib/swiper-4.3.5.min.css


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 13 - 0
public/static/lib/swiper-4.3.5.min.js


+ 4 - 0
public/static/worker.comments.js

@@ -0,0 +1,4 @@
+setInterval(() => {
+    self.postMessage({cmd:'list'})    
+}, 3000);
+

+ 14 - 0
src/App.vue

@@ -0,0 +1,14 @@
+<template>
+    <router-view />
+</template>
+<script>
+export default {
+    name: 'App',
+    created() {
+        document.addEventListener('touchmove', function(e) {
+            e.preventDefault()
+        }, { passive: false })
+    }
+}
+</script>
+<style lang="less" src="@/assets/styles/global.less"></style>

BIN
src/assets/images/logo.png


BIN
src/assets/images/心情墙.png


+ 357 - 0
src/assets/styles/_base.less

@@ -0,0 +1,357 @@
+/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
+
+*,
+*::before,
+*::after{
+    margin: 0;
+    padding: 0;
+    box-sizing: border-box;
+}
+
+/* Document
+   ========================================================================== */
+
+/**
+ * 1. Correct the line height in all browsers.
+ * 2. Prevent adjustments of font size after orientation changes in iOS.
+ */
+
+ html {
+    line-height: 1.15; /* 1 */
+    -webkit-text-size-adjust: 100%; /* 2 */
+  }
+  
+  /* Sections
+     ========================================================================== */
+  
+  /**
+   * Remove the margin in all browsers.
+   */
+  
+  body {
+    margin: 0;
+  }
+  
+  /**
+   * Render the `main` element consistently in IE.
+   */
+  
+  main {
+    display: block;
+  }
+  
+  /**
+   * Correct the font size and margin on `h1` elements within `section` and
+   * `article` contexts in Chrome, Firefox, and Safari.
+   */
+  
+  h1 {
+    font-size: 2em;
+    margin: 0.67em 0;
+  }
+  
+  /* Grouping content
+     ========================================================================== */
+  
+  /**
+   * 1. Add the correct box sizing in Firefox.
+   * 2. Show the overflow in Edge and IE.
+   */
+  
+  hr {
+    box-sizing: content-box; /* 1 */
+    height: 0; /* 1 */
+    overflow: visible; /* 2 */
+  }
+  
+  /**
+   * 1. Correct the inheritance and scaling of font size in all browsers.
+   * 2. Correct the odd `em` font sizing in all browsers.
+   */
+  
+  pre {
+    font-family: monospace, monospace; /* 1 */
+    font-size: 1em; /* 2 */
+  }
+  
+  /* Text-level semantics
+     ========================================================================== */
+  
+  /**
+   * Remove the gray background on active links in IE 10.
+   */
+  
+  a {
+    background-color: transparent;
+  }
+  
+  /**
+   * 1. Remove the bottom border in Chrome 57-
+   * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
+   */
+  
+  abbr[title] {
+    border-bottom: none; /* 1 */
+    text-decoration: underline; /* 2 */
+    text-decoration: underline dotted; /* 2 */
+  }
+  
+  /**
+   * Add the correct font weight in Chrome, Edge, and Safari.
+   */
+  
+  b,
+  strong {
+    font-weight: bolder;
+  }
+  
+  /**
+   * 1. Correct the inheritance and scaling of font size in all browsers.
+   * 2. Correct the odd `em` font sizing in all browsers.
+   */
+  
+  code,
+  kbd,
+  samp {
+    font-family: monospace, monospace; /* 1 */
+    font-size: 1em; /* 2 */
+  }
+  
+  /**
+   * Add the correct font size in all browsers.
+   */
+  
+  small {
+    font-size: 80%;
+  }
+  
+  /**
+   * Prevent `sub` and `sup` elements from affecting the line height in
+   * all browsers.
+   */
+  
+  sub,
+  sup {
+    font-size: 75%;
+    line-height: 0;
+    position: relative;
+    vertical-align: baseline;
+  }
+  
+  sub {
+    bottom: -0.25em;
+  }
+  
+  sup {
+    top: -0.5em;
+  }
+  
+  /* Embedded content
+     ========================================================================== */
+  
+  /**
+   * Remove the border on images inside links in IE 10.
+   */
+  
+  img {
+    border-style: none;
+  }
+  
+  /* Forms
+     ========================================================================== */
+  
+  /**
+   * 1. Change the font styles in all browsers.
+   * 2. Remove the margin in Firefox and Safari.
+   */
+  
+  button,
+  input,
+  optgroup,
+  select,
+  textarea {
+    font-family: inherit; /* 1 */
+    font-size: 100%; /* 1 */
+    line-height: 1.15; /* 1 */
+    margin: 0; /* 2 */
+  }
+  
+  /**
+   * Show the overflow in IE.
+   * 1. Show the overflow in Edge.
+   */
+  
+  button,
+  input { /* 1 */
+    overflow: visible;
+  }
+  
+  /**
+   * Remove the inheritance of text transform in Edge, Firefox, and IE.
+   * 1. Remove the inheritance of text transform in Firefox.
+   */
+  
+  button,
+  select { /* 1 */
+    text-transform: none;
+  }
+  
+  /**
+   * Correct the inability to style clickable types in iOS and Safari.
+   */
+  
+  button,
+  [type="button"],
+  [type="reset"],
+  [type="submit"] {
+    -webkit-appearance: button;
+  }
+  
+  /**
+   * Remove the inner border and padding in Firefox.
+   */
+  
+  button::-moz-focus-inner,
+  [type="button"]::-moz-focus-inner,
+  [type="reset"]::-moz-focus-inner,
+  [type="submit"]::-moz-focus-inner {
+    border-style: none;
+    padding: 0;
+  }
+  
+  /**
+   * Restore the focus styles unset by the previous rule.
+   */
+  
+  button:-moz-focusring,
+  [type="button"]:-moz-focusring,
+  [type="reset"]:-moz-focusring,
+  [type="submit"]:-moz-focusring {
+    outline: 1px dotted ButtonText;
+  }
+  
+  /**
+   * Correct the padding in Firefox.
+   */
+  
+  fieldset {
+    padding: 0.35em 0.75em 0.625em;
+  }
+  
+  /**
+   * 1. Correct the text wrapping in Edge and IE.
+   * 2. Correct the color inheritance from `fieldset` elements in IE.
+   * 3. Remove the padding so developers are not caught out when they zero out
+   *    `fieldset` elements in all browsers.
+   */
+  
+  legend {
+    box-sizing: border-box; /* 1 */
+    color: inherit; /* 2 */
+    display: table; /* 1 */
+    max-width: 100%; /* 1 */
+    padding: 0; /* 3 */
+    white-space: normal; /* 1 */
+  }
+  
+  /**
+   * Add the correct vertical alignment in Chrome, Firefox, and Opera.
+   */
+  
+  progress {
+    vertical-align: baseline;
+  }
+  
+  /**
+   * Remove the default vertical scrollbar in IE 10+.
+   */
+  
+  textarea {
+    overflow: auto;
+  }
+  
+  /**
+   * 1. Add the correct box sizing in IE 10.
+   * 2. Remove the padding in IE 10.
+   */
+  
+  [type="checkbox"],
+  [type="radio"] {
+    box-sizing: border-box; /* 1 */
+    padding: 0; /* 2 */
+  }
+  
+  /**
+   * Correct the cursor style of increment and decrement buttons in Chrome.
+   */
+  
+  [type="number"]::-webkit-inner-spin-button,
+  [type="number"]::-webkit-outer-spin-button {
+    height: auto;
+  }
+  
+  /**
+   * 1. Correct the odd appearance in Chrome and Safari.
+   * 2. Correct the outline style in Safari.
+   */
+  
+  [type="search"] {
+    -webkit-appearance: textfield; /* 1 */
+    outline-offset: -2px; /* 2 */
+  }
+  
+  /**
+   * Remove the inner padding in Chrome and Safari on macOS.
+   */
+  
+  [type="search"]::-webkit-search-decoration {
+    -webkit-appearance: none;
+  }
+  
+  /**
+   * 1. Correct the inability to style clickable types in iOS and Safari.
+   * 2. Change font properties to `inherit` in Safari.
+   */
+  
+  ::-webkit-file-upload-button {
+    -webkit-appearance: button; /* 1 */
+    font: inherit; /* 2 */
+  }
+  
+  /* Interactive
+     ========================================================================== */
+  
+  /*
+   * Add the correct display in Edge, IE 10+, and Firefox.
+   */
+  
+  details {
+    display: block;
+  }
+  
+  /*
+   * Add the correct display in all browsers.
+   */
+  
+  summary {
+    display: list-item;
+  }
+  
+  /* Misc
+     ========================================================================== */
+  
+  /**
+   * Add the correct display in IE 10+.
+   */
+  
+  template {
+    display: none;
+  }
+  
+  /**
+   * Add the correct display in IE 10.
+   */
+  
+  [hidden] {
+    display: none;
+  }

+ 5 - 0
src/assets/styles/_variables.less

@@ -0,0 +1,5 @@
+/*最大宽度*/
+@max-width:1200px;
+/*头部高度*/
+@top-height:60px;
+@color-primary:#EC652D;

+ 372 - 0
src/assets/styles/global.css

@@ -0,0 +1,372 @@
+/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
+*,
+*::before,
+*::after {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+}
+/* Document
+   ========================================================================== */
+/**
+ * 1. Correct the line height in all browsers.
+ * 2. Prevent adjustments of font size after orientation changes in iOS.
+ */
+html {
+  line-height: 1.15;
+  /* 1 */
+  -webkit-text-size-adjust: 100%;
+  /* 2 */
+}
+/* Sections
+     ========================================================================== */
+/**
+   * Remove the margin in all browsers.
+   */
+body {
+  margin: 0;
+}
+/**
+   * Render the `main` element consistently in IE.
+   */
+main {
+  display: block;
+}
+/**
+   * Correct the font size and margin on `h1` elements within `section` and
+   * `article` contexts in Chrome, Firefox, and Safari.
+   */
+h1 {
+  font-size: 2em;
+  margin: 0.67em 0;
+}
+/* Grouping content
+     ========================================================================== */
+/**
+   * 1. Add the correct box sizing in Firefox.
+   * 2. Show the overflow in Edge and IE.
+   */
+hr {
+  box-sizing: content-box;
+  /* 1 */
+  height: 0;
+  /* 1 */
+  overflow: visible;
+  /* 2 */
+}
+/**
+   * 1. Correct the inheritance and scaling of font size in all browsers.
+   * 2. Correct the odd `em` font sizing in all browsers.
+   */
+pre {
+  font-family: monospace, monospace;
+  /* 1 */
+  font-size: 1em;
+  /* 2 */
+}
+/* Text-level semantics
+     ========================================================================== */
+/**
+   * Remove the gray background on active links in IE 10.
+   */
+a {
+  background-color: transparent;
+}
+/**
+   * 1. Remove the bottom border in Chrome 57-
+   * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
+   */
+abbr[title] {
+  border-bottom: none;
+  /* 1 */
+  text-decoration: underline;
+  /* 2 */
+  text-decoration: underline dotted;
+  /* 2 */
+}
+/**
+   * Add the correct font weight in Chrome, Edge, and Safari.
+   */
+b,
+strong {
+  font-weight: bolder;
+}
+/**
+   * 1. Correct the inheritance and scaling of font size in all browsers.
+   * 2. Correct the odd `em` font sizing in all browsers.
+   */
+code,
+kbd,
+samp {
+  font-family: monospace, monospace;
+  /* 1 */
+  font-size: 1em;
+  /* 2 */
+}
+/**
+   * Add the correct font size in all browsers.
+   */
+small {
+  font-size: 80%;
+}
+/**
+   * Prevent `sub` and `sup` elements from affecting the line height in
+   * all browsers.
+   */
+sub,
+sup {
+  font-size: 75%;
+  line-height: 0;
+  position: relative;
+  vertical-align: baseline;
+}
+sub {
+  bottom: -0.25em;
+}
+sup {
+  top: -0.5em;
+}
+/* Embedded content
+     ========================================================================== */
+/**
+   * Remove the border on images inside links in IE 10.
+   */
+img {
+  border-style: none;
+}
+/* Forms
+     ========================================================================== */
+/**
+   * 1. Change the font styles in all browsers.
+   * 2. Remove the margin in Firefox and Safari.
+   */
+button,
+input,
+optgroup,
+select,
+textarea {
+  font-family: inherit;
+  /* 1 */
+  font-size: 100%;
+  /* 1 */
+  line-height: 1.15;
+  /* 1 */
+  margin: 0;
+  /* 2 */
+}
+/**
+   * Show the overflow in IE.
+   * 1. Show the overflow in Edge.
+   */
+button,
+input {
+  /* 1 */
+  overflow: visible;
+}
+/**
+   * Remove the inheritance of text transform in Edge, Firefox, and IE.
+   * 1. Remove the inheritance of text transform in Firefox.
+   */
+button,
+select {
+  /* 1 */
+  text-transform: none;
+}
+/**
+   * Correct the inability to style clickable types in iOS and Safari.
+   */
+button,
+[type="button"],
+[type="reset"],
+[type="submit"] {
+  -webkit-appearance: button;
+}
+/**
+   * Remove the inner border and padding in Firefox.
+   */
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner {
+  border-style: none;
+  padding: 0;
+}
+/**
+   * Restore the focus styles unset by the previous rule.
+   */
+button:-moz-focusring,
+[type="button"]:-moz-focusring,
+[type="reset"]:-moz-focusring,
+[type="submit"]:-moz-focusring {
+  outline: 1px dotted ButtonText;
+}
+/**
+   * Correct the padding in Firefox.
+   */
+fieldset {
+  padding: 0.35em 0.75em 0.625em;
+}
+/**
+   * 1. Correct the text wrapping in Edge and IE.
+   * 2. Correct the color inheritance from `fieldset` elements in IE.
+   * 3. Remove the padding so developers are not caught out when they zero out
+   *    `fieldset` elements in all browsers.
+   */
+legend {
+  box-sizing: border-box;
+  /* 1 */
+  color: inherit;
+  /* 2 */
+  display: table;
+  /* 1 */
+  max-width: 100%;
+  /* 1 */
+  padding: 0;
+  /* 3 */
+  white-space: normal;
+  /* 1 */
+}
+/**
+   * Add the correct vertical alignment in Chrome, Firefox, and Opera.
+   */
+progress {
+  vertical-align: baseline;
+}
+/**
+   * Remove the default vertical scrollbar in IE 10+.
+   */
+textarea {
+  overflow: auto;
+}
+/**
+   * 1. Add the correct box sizing in IE 10.
+   * 2. Remove the padding in IE 10.
+   */
+[type="checkbox"],
+[type="radio"] {
+  box-sizing: border-box;
+  /* 1 */
+  padding: 0;
+  /* 2 */
+}
+/**
+   * Correct the cursor style of increment and decrement buttons in Chrome.
+   */
+[type="number"]::-webkit-inner-spin-button,
+[type="number"]::-webkit-outer-spin-button {
+  height: auto;
+}
+/**
+   * 1. Correct the odd appearance in Chrome and Safari.
+   * 2. Correct the outline style in Safari.
+   */
+[type="search"] {
+  -webkit-appearance: textfield;
+  /* 1 */
+  outline-offset: -2px;
+  /* 2 */
+}
+/**
+   * Remove the inner padding in Chrome and Safari on macOS.
+   */
+[type="search"]::-webkit-search-decoration {
+  -webkit-appearance: none;
+}
+/**
+   * 1. Correct the inability to style clickable types in iOS and Safari.
+   * 2. Change font properties to `inherit` in Safari.
+   */
+::-webkit-file-upload-button {
+  -webkit-appearance: button;
+  /* 1 */
+  font: inherit;
+  /* 2 */
+}
+/* Interactive
+     ========================================================================== */
+/*
+   * Add the correct display in Edge, IE 10+, and Firefox.
+   */
+details {
+  display: block;
+}
+/*
+   * Add the correct display in all browsers.
+   */
+summary {
+  display: list-item;
+}
+/* Misc
+     ========================================================================== */
+/**
+   * Add the correct display in IE 10+.
+   */
+template {
+  display: none;
+}
+/**
+   * Add the correct display in IE 10.
+   */
+[hidden] {
+  display: none;
+}
+/*最大宽度*/
+/*头部高度*/
+html,
+body {
+  height: 100%;
+  overflow: hidden;
+}
+body {
+  font-family: "Microsoft YaHei";
+  -webkit-user-select: text;
+     -moz-user-select: text;
+      -ms-user-select: text;
+          user-select: text;
+  outline: none;
+  -webkit-appearance: none;
+     -moz-appearance: none;
+          appearance: none;
+  -webkit-tap-highlight-color: rgba(255, 255, 255, 0);
+}
+.icon {
+  display: inline-block;
+}
+.clearfix:after {
+  visibility: hidden;
+  display: block;
+  font-size: 0;
+  content: " ";
+  clear: both;
+  height: 0;
+}
+.clearfix {
+  display: block;
+}
+section.max-width {
+  width: 1200px;
+  margin: 0 auto;
+}
+.swiper-slide {
+  text-align: center;
+  font-size: 18px;
+  background: #fff;
+  /* Center slide text vertically */
+  display: -webkit-box;
+  display: -ms-flexbox;
+  display: -webkit-flex;
+  display: flex;
+  -webkit-box-pack: center;
+  -ms-flex-pack: center;
+  -webkit-justify-content: center;
+  justify-content: center;
+  -webkit-box-align: center;
+  -ms-flex-align: center;
+  -webkit-align-items: center;
+  align-items: center;
+}
+.el-message {
+  min-width: 100px !important;
+  top: 25% !important;
+  white-space: nowrap;
+}

+ 64 - 0
src/assets/styles/global.less

@@ -0,0 +1,64 @@
+@import './_base.less';
+@import './_variables.less';
+
+html,body{
+    height: 100%;
+    overflow: hidden;
+}
+body{
+    font-family: "Microsoft YaHei";
+    user-select: text;
+    outline: none;
+    appearance: none;
+    -webkit-tap-highlight-color: rgba(255,255,255,0);
+}
+
+.icon{
+    display: inline-block;
+}
+
+.clearfix:after {
+    visibility: hidden;
+    display: block;
+    font-size: 0;
+    content: " ";
+    clear: both;
+    height: 0;
+}
+
+.clearfix {
+    display: block;
+}
+
+section.max-width {
+    width: @max-width;
+    margin: 0 auto;
+}
+
+.swiper-slide {
+    text-align: center;
+    font-size: 18px;
+    background: #fff;
+    /* Center slide text vertically */
+    display: -webkit-box;
+    display: -ms-flexbox;
+    display: -webkit-flex;
+    display: flex;
+    -webkit-box-pack: center;
+    -ms-flex-pack: center;
+    -webkit-justify-content: center;
+    justify-content: center;
+    -webkit-box-align: center;
+    -ms-flex-align: center;
+    -webkit-align-items: center;
+    align-items: center;
+}
+
+.el-message{
+    min-width: 100px !important;
+    top: 25% !important;
+    white-space: nowrap;
+}
+// .el-upload-list.el-upload-list--text{
+//     display: none !important;
+// }

+ 15 - 0
src/auth.js

@@ -0,0 +1,15 @@
+import 'nprogress/nprogress.css'
+import NProgress from 'nprogress'
+import router from './router'
+
+NProgress.configure({ showSpinner: false })
+
+router.beforeEach((to, from, next) => {
+    NProgress.start()
+    next()
+})
+
+router.afterEach(() => {
+    NProgress.done()
+  })
+  

+ 116 - 0
src/components/BackToTop/index.vue

@@ -0,0 +1,116 @@
+<template>
+  <transition :name="transitionName">
+    <div v-show="visible" :style="customStyle" class="back-to-ceiling" @click="backToTop">
+      <svg width="16" height="16" viewBox="0 0 17 17" xmlns="http://www.w3.org/2000/svg" class="Icon Icon--backToTopArrow" aria-hidden="true" style="height: 16px; width: 16px;">
+        <title>回到顶部</title>
+        <g>
+          <path d="M12.036 15.59c0 .55-.453.995-.997.995H5.032c-.55 0-.997-.445-.997-.996V8.584H1.03c-1.1 0-1.36-.633-.578-1.416L7.33.29c.39-.39 1.026-.385 1.412 0l6.878 6.88c.782.78.523 1.415-.58 1.415h-3.004v7.004z" fill-rule="evenodd"/>
+        </g>
+      </svg>
+    </div>
+  </transition>
+</template>
+
+<script>
+export default {
+  name: 'BackToTop',
+  props: {
+    visibilityHeight: {
+      type: Number,
+      default: 400
+    },
+    backPosition: {
+      type: Number,
+      default: 0
+    },
+    customStyle: {
+      type: Object,
+      default: function() {
+        return {
+          right: '50px',
+          bottom: '50px',
+          width: '40px',
+          height: '40px',
+          'border-radius': '4px',
+          'line-height': '45px',
+          background: '#e7eaf1'
+        }
+      }
+    },
+    transitionName: {
+      type: String,
+      default: 'fade'
+    }
+  },
+  data() {
+    return {
+      visible: false,
+      interval: null,
+      isMoving: false
+    }
+  },
+  mounted() {
+    window.addEventListener('scroll', this.handleScroll)
+  },
+  beforeDestroy() {
+    window.removeEventListener('scroll', this.handleScroll)
+    if (this.interval) {
+      clearInterval(this.interval)
+    }
+  },
+  methods: {
+    handleScroll() {
+      this.visible = window.pageYOffset > this.visibilityHeight
+    },
+    backToTop() {
+      if (this.isMoving) return
+      const start = window.pageYOffset
+      let i = 0
+      this.isMoving = true
+      this.interval = setInterval(() => {
+        const next = Math.floor(this.easeInOutQuad(10 * i, start, -start, 500))
+        if (next <= this.backPosition) {
+          window.scrollTo(0, this.backPosition)
+          clearInterval(this.interval)
+          this.isMoving = false
+        } else {
+          window.scrollTo(0, next)
+        }
+        i++
+      }, 16.7)
+    },
+    easeInOutQuad(t, b, c, d) {
+      if ((t /= d / 2) < 1) return c / 2 * t * t + b
+      return -c / 2 * (--t * (t - 2) - 1) + b
+    }
+  }
+}
+</script>
+
+<style scoped>
+  .back-to-ceiling {
+    position: fixed;
+    display: inline-block;
+    text-align: center;
+    cursor: pointer;
+  }
+
+  .back-to-ceiling:hover {
+    background: #d5dbe7;
+  }
+
+  .fade-enter-active,
+  .fade-leave-active {
+    transition: opacity .5s;
+  }
+
+  .fade-enter,
+  .fade-leave-to {
+    opacity: 0
+  }
+
+  .back-to-ceiling .Icon {
+    fill: #9aaabf;
+    background: none;
+  }
+</style>

+ 43 - 0
src/components/SvgIcon/index.vue

@@ -0,0 +1,43 @@
+<template>
+  <svg :class="svgClass" aria-hidden="true">
+    <use :xlink:href="iconName"/>
+  </svg>
+</template>
+
+<script>
+export default {
+  name: 'SvgIcon',
+  props: {
+    iconClass: {
+      type: String,
+      required: true
+    },
+    className: {
+      type: String,
+      default: ''
+    }
+  },
+  computed: {
+    iconName() {
+      return `#icon-${this.iconClass}`
+    },
+    svgClass() {
+      if (this.className) {
+        return 'svg-icon ' + this.className
+      } else {
+        return 'svg-icon'
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+.svg-icon {
+  width: 1em;
+  height: 1em;
+  vertical-align: -0.15em;
+  fill: currentColor;
+  overflow: hidden;
+}
+</style>

+ 365 - 0
src/config/fonts.js

@@ -0,0 +1,365 @@
+export default {
+    windows: [{
+        ch: '宋体',
+        en: 'SimSun'
+    }, {
+        ch: '黑体',
+        en: 'SimHei'
+    }, {
+        ch: '微软雅黑',
+        en: 'Microsoft Yahei'
+    }, {
+        ch: '微软正黑体',
+        en: 'Microsoft JhengHei'
+    }, {
+        ch: '楷体',
+        en: 'KaiTi'
+    }, {
+        ch: '新宋体',
+        en: 'NSimSun'
+    }, {
+        ch: '仿宋',
+        en: 'FangSong'
+    }],
+    'OS X': [{
+        ch: '苹方',
+        en: 'PingFang SC'
+    }, {
+        ch: '华文黑体',
+        en: 'STHeiti'
+    }, {
+        ch: '华文楷体',
+        en: 'STKaiti'
+    }, {
+        ch: '华文宋体',
+        en: 'STSong'
+    }, {
+        ch: '华文仿宋',
+        en: 'STFangsong'
+    }, {
+        ch: '华文中宋',
+        en: 'STZhongsong'
+    }, {
+        ch: '华文琥珀',
+        en: 'STHupo'
+    }, {
+        ch: '华文新魏',
+        en: 'STXinwei'
+    }, {
+        ch: '华文隶书',
+        en: 'STLiti'
+    }, {
+        ch: '华文行楷',
+        en: 'STXingkai'
+    }, {
+        ch: '冬青黑体简',
+        en: 'Hiragino Sans GB'
+    }, {
+        ch: '兰亭黑-简',
+        en: 'Lantinghei SC'
+    }, {
+        ch: '翩翩体-简',
+        en: 'Hanzipen SC'
+    }, {
+        ch: '手札体-简',
+        en: 'Hannotate SC'
+    }, {
+        ch: '宋体-简',
+        en: 'Songti SC'
+    }, {
+        ch: '娃娃体-简',
+        en: 'Wawati SC'
+    }, {
+        ch: '魏碑-简',
+        en: 'Weibei SC'
+    }, {
+        ch: '行楷-简',
+        en: 'Xingkai SC'
+    }, {
+        ch: '雅痞-简',
+        en: 'Yapi SC'
+    }, {
+        ch: '圆体-简',
+        en: 'Yuanti SC'
+    }],
+    'office': [{
+        ch: '幼圆',
+        en: 'YouYuan'
+    }, {
+        ch: '隶书',
+        en: 'LiSu'
+    }, {
+        ch: '华文细黑',
+        en: 'STXihei'
+    }, {
+        ch: '华文楷体',
+        en: 'STKaiti'
+    }, {
+        ch: '华文宋体',
+        en: 'STSong'
+    }, {
+        ch: '华文仿宋',
+        en: 'STFangsong'
+    }, {
+        ch: '华文中宋',
+        en: 'STZhongsong'
+    }, {
+        ch: '华文彩云',
+        en: 'STCaiyun'
+    }, {
+        ch: '华文琥珀',
+        en: 'STHupo'
+    }, {
+        ch: '华文新魏',
+        en: 'STXinwei'
+    }, {
+        ch: '华文隶书',
+        en: 'STLiti'
+    }, {
+        ch: '华文行楷',
+        en: 'STXingkai'
+    }, {
+        ch: '方正舒体',
+        en: 'FZShuTi'
+    }, {
+        ch: '方正姚体',
+        en: 'FZYaoti'
+    }],
+    'open': [{
+        ch: '思源黑体',
+        en: 'Source Han Sans CN'
+    }, {
+        ch: '思源宋体',
+        en: 'Source Han Serif SC'
+    }, {
+        ch: '文泉驿微米黑',
+        en: 'WenQuanYi Micro Hei'
+    }],
+    'hanyi': [{
+        ch: '汉仪旗黑',
+        en: 'HYQihei 40S'
+    }, {
+        ch: '汉仪旗黑',
+        en: 'HYQihei 50S'
+    }, {
+        ch: '汉仪旗黑',
+        en: 'HYQihei 60S'
+    }, {
+        ch: '汉仪大宋简',
+        en: 'HYDaSongJ'
+    }, {
+        ch: '汉仪楷体',
+        en: 'HYKaiti'
+    }, {
+        ch: '汉仪家书简',
+        en: 'HYJiaShuJ'
+    }, {
+        ch: '汉仪PP体简',
+        en: 'HYPPTiJ'
+    }, {
+        ch: '汉仪乐喵体简',
+        en: 'HYLeMiaoTi'
+    }, {
+        ch: '汉仪小麦体',
+        en: 'HYXiaoMaiTiJ'
+    }, {
+        ch: '汉仪程行体',
+        en: 'HYChengXingJ'
+    }, {
+        ch: '汉仪黑荔枝',
+        en: 'HYHeiLiZhiTiJ'
+    }, {
+        ch: '汉仪雅酷黑W',
+        en: 'HYYaKuHeiW'
+    }, {
+        ch: '汉仪大黑简',
+        en: 'HYDaHeiJ'
+    }, {
+        ch: '汉仪尚魏手书W',
+        en: 'HYShangWeiShouShuW'
+    }],
+    'fangzheng': [{
+        "ch": "方正粗雅宋简体",
+        "en": "FZYaSongS-B-GB"
+    }, {
+        "ch": "方正报宋简体",
+        "en": "FZBaoSong-Z04S"
+    }, {
+        "ch": "方正粗圆简体",
+        "en": "FZCuYuan-M03S"
+    }, {
+        "ch": "方正大标宋简体",
+        "en": "FZDaBiaoSong-B06S"
+    }, {
+        "ch": "方正大黑简体",
+        "en": "FZDaHei-B02S"
+    }, {
+        "ch": "方正仿宋简体",
+        "en": "FZFangSong-Z02S"
+    }, {
+        "ch": "方正黑体简体",
+        "en": "FZHei-B01S"
+    }, {
+        "ch": "方正琥珀简体",
+        "en": "FZHuPo-M04S"
+    }, {
+        "ch": "方正楷体简体",
+        "en": "FZKai-Z03S"
+    }, {
+        "ch": "方正隶变简体",
+        "en": "FZLiBian-S02S"
+    }, {
+        "ch": "方正隶书简体",
+        "en": "FZLiShu-S01S"
+    }, {
+        "ch": "方正美黑简体",
+        "en": "FZMeiHei-M07S"
+    }, {
+        "ch": "方正书宋简体",
+        "en": "FZShuSong-Z01S"
+    }, {
+        "ch": "方正舒体简体",
+        "en": "FZShuTi-S05S"
+    }, {
+        "ch": "方正水柱简体",
+        "en": "FZShuiZhu-M08S"
+    }, {
+        "ch": "方正宋黑简体",
+        "en": "FZSongHei-B07S"
+    }, {
+        "ch": "方正宋三简体",
+        "en": "FZSong"
+    }, {
+        "ch": "方正魏碑简体",
+        "en": "FZWeiBei-S03S"
+    }, {
+        "ch": "方正细等线简体",
+        "en": "FZXiDengXian-Z06S"
+    }, {
+        "ch": "方正细黑一简体",
+        "en": "FZXiHei I-Z08S"
+    }, {
+        "ch": "方正细圆简体",
+        "en": "FZXiYuan-M01S"
+    }, {
+        "ch": "方正小标宋简体",
+        "en": "FZXiaoBiaoSong-B05S"
+    }, {
+        "ch": "方正行楷简体",
+        "en": "FZXingKai-S04S"
+    }, {
+        "ch": "方正姚体简体",
+        "en": "FZYaoTi-M06S"
+    }, {
+        "ch": "方正中等线简体",
+        "en": "FZZhongDengXian-Z07S"
+    }, {
+        "ch": "方正准圆简体",
+        "en": "FZZhunYuan-M02S"
+    }, {
+        "ch": "方正综艺简体",
+        "en": "FZZongYi-M05S"
+    }, {
+        "ch": "方正彩云简体",
+        "en": "FZCaiYun-M09S"
+    }, {
+        "ch": "方正隶二简体",
+        "en": "FZLiShu II-S06S"
+    }, {
+        "ch": "方正康体简体",
+        "en": "FZKangTi-S07S"
+    }, {
+        "ch": "方正超粗黑简体",
+        "en": "FZChaoCuHei-M10S"
+    }, {
+        "ch": "方正新报宋简体",
+        "en": "FZNew BaoSong-Z12S"
+    }, {
+        "ch": "方正新舒体简体",
+        "en": "FZNew ShuTi-S08S"
+    }, {
+        "ch": "方正黄草简体",
+        "en": "FZHuangCao-S09S"
+    }, {
+        "ch": "方正少儿简体",
+        "en": "FZShaoEr-M11S"
+    }, {
+        "ch": "方正稚艺简体",
+        "en": "FZZhiYi-M12S"
+    }, {
+        "ch": "方正细珊瑚简体",
+        "en": "FZXiShanHu-M13S"
+    }, {
+        "ch": "方正粗宋简体",
+        "en": "FZCuSong-B09S"
+    }, {
+        "ch": "方正平和简体",
+        "en": "FZPingHe-S11S"
+    }, {
+        "ch": "方正华隶简体",
+        "en": "FZHuaLi-M14S"
+    }, {
+        "ch": "方正瘦金书简体",
+        "en": "FZShouJinShu-S10S"
+    }, {
+        "ch": "方正细倩简体",
+        "en": "FZXiQian-M15S"
+    }, {
+        "ch": "方正中倩简体",
+        "en": "FZZhongQian-M16S"
+    }, {
+        "ch": "方正粗倩简体",
+        "en": "FZCuQian-M17S"
+    }, {
+        "ch": "方正胖娃简体",
+        "en": "FZPangWa-M18S"
+    }, {
+        "ch": "方正宋一简体",
+        "en": "FZSongYi-Z13S"
+    }, {
+        "ch": "方正剪纸简体",
+        "en": "FZJianZhi-M23S"
+    }, {
+        "ch": "方正流行体简体",
+        "en": "FZLiuXingTi-M26S"
+    }, {
+        "ch": "方正祥隶简体",
+        "en": "FZXiangLi-S17S"
+    }, {
+        "ch": "方正粗活意简体",
+        "en": "FZCuHuoYi-M25S"
+    }, {
+        "ch": "方正胖头鱼简体",
+        "en": "FZPangTouYu-M24S"
+    }, {
+        "ch": "方正卡通简体",
+        "en": "FZKaTong-M19S"
+    }, {
+        "ch": "方正艺黑简体",
+        "en": "FZYiHei-M20S"
+    }, {
+        "ch": "方正水黑简体",
+        "en": "FZShuiHei-M21S"
+    }, {
+        "ch": "方正古隶简体",
+        "en": "FZGuLi-S12S"
+    }, {
+        "ch": "方正幼线简体",
+        "en": "FZYouXian-Z09S"
+    }, {
+        "ch": "方正启体简体",
+        "en": "FZQiTi-S14S"
+    }, {
+        "ch": "方正小篆体",
+        "en": "FZXiaoZhuanTi-S13T"
+    }, {
+        "ch": "方正硬笔楷书简体",
+        "en": "FZYingBiKaiShu-S15S"
+    }, {
+        "ch": "方正毡笔黑简体",
+        "en": "FZZhanBiHei-M22S"
+    }, {
+        "ch": "方正硬笔行书简体",
+        "en": "FZYingBiXingShu-S16S"
+    }]
+};

+ 9 - 0
src/icons/index.js

@@ -0,0 +1,9 @@
+import Vue from 'vue'
+import SvgIcon from '@/components/SvgIcon'// svg组件
+
+// register globally
+Vue.component('svg-icon', SvgIcon)
+
+const req = require.context('./svg', false, /\.svg$/)
+const requireAll = requireContext => requireContext.keys().map(requireContext)
+requireAll(req)

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 0
src/icons/svg/colors.svg


+ 1 - 0
src/icons/svg/fonts.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 112 112"><path d="M0 112v-8l84.7.2v7.8H0zm84.3-77l13.6 19.1L112 35H84.3zM23.2 51.6h38.3l15.9 34.9h7.3L46.7 0H38L0 86.5h7.3l15.9-34.9zM42.3 9.7l15.6 34.2H26.7L42.3 9.7zm0 0"/></svg>

+ 40 - 0
src/icons/svg/keyboard.svg

@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 128 124" style="enable-background:new 0 0 128 124;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:currentColor;}
+	.st1{fill:#FFFFFF;}
+	.st2{fill:#3566E1;}
+</style>
+<g id="bg">
+	<rect class="st0" width="128" height="124"/>
+</g>
+<g id="square">
+	<path class="st1" d="M121.9,77.2H81.3v40.7h-61C9.1,117.9,0,108.8,0,97.6V20.3C0,9.1,9.1,0,20.3,0h81.3c11.2,0,20.3,9.1,20.3,20.3
+		V77.2z M87.4,83.3V124h32.5c4.5,0,8.1-3.6,8.1-8.1V83.3H87.4z"/>
+</g>
+<g id="key">
+	<g>
+		<rect x="19.5" y="33.8" class="st2" width="13.5" height="9"/>
+		<rect x="41.3" y="33.8" class="st2" width="13.5" height="9"/>
+		<rect x="63.1" y="33.8" class="st2" width="13.5" height="9"/>
+		<rect x="85" y="33.8" class="st2" width="13.5" height="9"/>
+		<rect x="30.8" y="56.4" class="st2" width="13.5" height="9"/>
+		<rect x="52.2" y="56.4" class="st2" width="13.5" height="9"/>
+		<rect x="73.7" y="56.4" class="st2" width="13.5" height="9"/>
+		<rect x="35.3" y="81.2" class="st2" width="36.1" height="9"/>
+	</g>
+	<g>
+		<path class="st2" d="M103.4,108.6c0.2,0.7,0.5,1.7,0.8,2.1c-3.7,2.8-4.4,3.4-4.7,3.9l0-0.1v0.1c-0.2-0.5-0.9-1.3-1.2-1.7
+			c0.4-0.4,1.1-1.2,1.1-2.5v-3.9h-2.2v-2.4h2.2v-2.5h-1.2v-1.9c-0.2,0.2-0.3,0.4-0.5,0.7c-0.2-0.5-0.7-1.8-1.1-2.4
+			c1-1.3,1.9-3.4,2.4-5.4l2.1,0.6c-0.1,0.5-0.3,1.1-0.5,1.7h3.3v2.4h-4.3c-0.3,0.7-0.7,1.3-1.1,2h4.8v2.4h-1.7v2.5h2.2v2.4h-2.2v3.4
+			L103.4,108.6z M109.4,101.4c-0.3,3.4-0.7,6.1-1.5,8.3c1.7,1.9,3.9,2.4,6.4,2.4c0.7,0,3.2,0,4.2,0c-0.3,0.6-0.7,1.7-0.8,2.4h-3.6
+			c-2.9,0-5.3-0.5-7.2-2.5c-0.6,1.2-1.4,2.1-2.2,2.8c-0.3-0.5-1.2-1.3-1.7-1.5c1-0.8,1.8-1.9,2.5-3.2c-0.6-1.1-1.2-2.5-1.6-4.2
+			l2-0.7c0.2,0.7,0.4,1.4,0.6,2c0.3-1.2,0.5-2.4,0.6-3.9h-3c0.6-1.8,1.5-4.3,2.1-6.7h-2v-2.3h4.9c-0.6,2.2-1.4,4.7-2.1,6.9h0.6
+			l0.4,0L109.4,101.4z M112,96.5h-2.2v-2h2.2v-1.7h2.2v1.7h3.3v3.1h0.7v2h-0.7v3.1h-3.3v1.1h3.1v2.2h-3.1v1.1h3.4v2.2h-3.4v2.1H112
+			v-2.1h-2.9v-2.2h2.9V106h-2.4v-2.2h2.4v-1.1h-2.2v-2h2.2v-1.1h-3.2v-2h3.2V96.5z M114.1,96.5v1.1h1.2v-1.1H114.1z M115.4,99.6
+			h-1.2v1.1h1.2V99.6z"/>
+	</g>
+</g>
+</svg>

+ 30 - 0
src/icons/svg/select.svg

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 128 124" style="enable-background:new 0 0 128 124;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:currentColor;}
+	.st1{fill:#FFFFFF;}
+	.st2{fill:#3566E1;}
+</style>
+<g id="bg">
+	<rect class="st0" width="128" height="124"/>
+</g>
+<g id="square">
+	<path class="st1" d="M121.9,77.2H81.3v40.7h-61C9.1,117.9,0,108.8,0,97.6V20.3C0,9.1,9.1,0,20.3,0h81.3c11.2,0,20.3,9.1,20.3,20.3
+		V77.2z M87.4,83.3V124h32.5c4.5,0,8.1-3.6,8.1-8.1V83.3H87.4z"/>
+</g>
+<g id="select">
+	<path class="st2" d="M37.3,48.3h-14v-8h14V48.3z M93.7,40.3h-48v8h48V40.3z M37.3,55.3h-14v8h14V55.3z M93.7,55.3h-48v8h48V55.3z
+		 M37.3,70.3h-14v8h14V70.3z M73.7,70.3h-28v8h28V70.3z"/>
+	<g>
+		<path class="st2" d="M102.1,109.3c0.6,0.1,1.1,0.6,2,1.2c1.3,0.8,3.2,0.9,5.4,0.9c2.1,0,5.4-0.2,7.5-0.5c-0.3,0.7-0.7,1.9-0.7,2.6
+			c-1.6,0.1-4.8,0.2-6.8,0.2c-2.5,0-4.2-0.3-5.7-1.1c-0.9-0.5-1.5-1.1-2-1.1c-0.8,0-2,1.2-3.1,2.6l-1.7-2.2c0.9-0.8,1.8-1.4,2.6-1.9
+			v-5.5h-2.3v-2.3h4.8V109.3z M100.5,99.6c-0.6-1-2-2.5-3.2-3.5l1.9-1.4c1.2,1,2.7,2.4,3.4,3.3L100.5,99.6z M109.2,103.5
+			c-0.4,3-1.4,5.4-5,6.9c-0.3-0.7-1-1.6-1.5-2.1c2.9-1,3.6-2.7,3.9-4.8h-3.5v-2.2h5.8v-2.5h-2.7c-0.4,0.8-0.9,1.5-1.4,2.1
+			c-0.5-0.4-1.5-1-2.1-1.3c1.2-1.2,2.1-3,2.6-4.9l2.4,0.5c-0.1,0.5-0.3,1-0.5,1.5h1.7v-2.6h2.5v2.6h4.4v2.1h-4.4v2.5h5.3v2.2H113
+			v3.7c0,0.6,0.1,0.7,0.4,0.7h0.9c0.3,0,0.4-0.3,0.5-2.2c0.5,0.4,1.5,0.8,2.2,1c-0.3,2.8-0.9,3.6-2.4,3.6H113c-2,0-2.5-0.7-2.5-3
+			v-3.7H109.2z"/>
+	</g>
+</g>
+</svg>

+ 30 - 0
src/icons/svg/upload.svg

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 128 124" style="enable-background:new 0 0 128 124;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:currentColor}
+	.st1{fill:#FFFFFF;}
+	.st2{fill:#3566E1;}
+</style>
+<g id="bg">
+	<rect class="st0" width="128" height="124"/>
+</g>
+<g id="square">
+	<path class="st1" d="M121.9,77.2H81.3v40.7h-61C9.1,117.9,0,108.8,0,97.6V20.3C0,9.1,9.1,0,20.3,0h81.3c11.2,0,20.3,9.1,20.3,20.3
+		V77.2z M87.4,83.3V124h32.5c4.5,0,8.1-3.6,8.1-8.1V83.3H87.4z"/>
+</g>
+<g id="upload">
+	<g>
+		<path class="st2" d="M103.6,95.5c-0.6,1.5-1.3,3-2.1,4.5v14.6h-2.4v-10.8c-0.4,0.6-0.9,1.1-1.3,1.6c-0.2-0.6-0.9-2-1.4-2.7
+			c1.9-1.9,3.7-5,4.8-8L103.6,95.5z M108.2,103.2c-0.2,0.6-0.3,1.2-0.5,1.8h6l0.4-0.1l1.8,1.2c-1.3,1.5-3,3.4-4.7,5.1
+			c0.8,0.6,1.5,1.2,2,1.6l-1.8,1.9c-1.2-1.2-3.7-3.2-5.8-4.4l1.8-1.5c0.6,0.3,1.2,0.7,1.8,1.1c0.8-0.8,1.6-1.6,2.3-2.4h-7.1
+			c0.4-1.2,0.8-2.6,1.3-4.2h-3.3v-2.4h3.9c0.1-0.6,0.3-1.1,0.4-1.7h-3.2v-2.3h3.7c0.2-0.7,0.3-1.4,0.5-2l2.5,0.3l-0.4,1.7h5.5v2.3
+			h-6.1l-0.4,1.7h7.6v2.4H108.2z"/>
+	</g>
+	<g>
+		<polygon class="st2" points="32,68.7 24,68.7 24,88.3 24,92 24,96.3 80,96.3 80,88.3 32,88.3 		"/>
+		<polygon class="st2" points="54,32.2 54,76 62,76 62,32.2 74.9,46.6 80.7,41.2 58,16 35.3,41.2 41.1,46.6 		"/>
+	</g>
+</g>
+</svg>

+ 30 - 0
src/icons/svg/write.svg

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 128 124" style="enable-background:new 0 0 128 124;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:currentColor;}
+	.st1{fill:#FFFFFF;}
+	.st2{fill:#3566E1;}
+</style>
+<g id="bg">
+	<rect class="st0" width="128" height="124"/>
+</g>
+<g id="square">
+	<path class="st1" d="M121.9,77.2H81.3v40.7h-61C9.1,117.9,0,108.8,0,97.6V20.3C0,9.1,9.1,0,20.3,0h81.3c11.2,0,20.3,9.1,20.3,20.3
+		V77.2z M87.4,83.3V124h32.5c4.5,0,8.1-3.6,8.1-8.1V83.3H87.4z"/>
+</g>
+<g id="pen">
+	<g>
+		<path class="st2" d="M118.1,93.9v5.5h-3v-2.8H99.8v2.8h-2.9v-5.5H118.1z M111,110.7H97.4V108H111V110.7z M116,103.8
+			c0,0,0,0.8-0.1,1.2c-0.5,5.9-1.1,8.4-2.1,9.4c-0.7,0.7-1.4,1-2.5,1c-0.9,0.1-2.5,0.1-4,0c0-0.8-0.4-2-1-2.7
+			c1.6,0.1,3.2,0.1,3.9,0.1c0.5,0,0.9,0,1.2-0.3c0.6-0.5,1.1-2.4,1.5-6.3h-12.6c0.7-2.4,1.5-6.4,2-9.4l2.9,0.3l-0.4,2h10.1v2.5
+			h-10.6c-0.1,0.7-0.3,1.4-0.4,2.1H116z"/>
+	</g>
+	<g>
+		<path class="st2" d="M54.7,79.6c-3.1,2.7-16.7,8.8-24.7,3c0,0,2.8-2.1,4.9-6.4C39.9,63.2,52.5,65,52.5,65l4.3,4.2
+			C56.9,68.9,60,74.7,54.7,79.6L54.7,79.6z"/>
+		<path class="st2" d="M96.6,32.7L61.5,66.2l-6.4-6.3l35.1-33.6c1.8-1.8,4.6-1.8,6.4,0C98.5,28.2,98.5,30.9,96.6,32.7L96.6,32.7z"/>
+	</g>
+</g>
+</svg>

+ 22 - 0
src/icons/svgo.yml

@@ -0,0 +1,22 @@
+# replace default config
+
+# multipass: true
+# full: true
+
+plugins:
+
+  # - name
+  #
+  # or:
+  # - name: false
+  # - name: true
+  #
+  # or:
+  # - name:
+  #     param1: 1
+  #     param2: 2
+
+- removeAttrs:
+    attrs:
+      - 'fill'
+      - 'fill-rule'

+ 22 - 0
src/main.js

@@ -0,0 +1,22 @@
+import './auth'
+import './plugins'
+import './icons'
+
+
+import Vue from 'vue'
+import App from './App.vue'
+import router from './router'
+import store from './store'
+import http from './utils/http'
+import bus from './utils/bus'
+
+Vue.config.productionTip = false
+
+Vue.prototype.$http = http
+Vue.prototype.$bus = bus
+
+new Vue({
+  router,
+  store,
+  render: h => h(App)
+}).$mount('#app')

+ 35 - 0
src/plugins.js

@@ -0,0 +1,35 @@
+import Vue from 'vue'
+import {
+    Tag,
+    Tabs,
+    TabPane,
+    Switch,
+    Button,
+    Form,
+    FormItem,
+    Input,
+    InputNumber,
+    Table,
+    TableColumn,
+    Upload,
+    Message,
+    Loading
+} from 'element-ui'
+
+Vue.use(Loading.directive);
+Vue.component(Tag.name, Tag)
+Vue.component(Tabs.name, Tabs)
+Vue.component(TabPane.name, TabPane)
+Vue.component(Switch.name, Switch)
+Vue.component(Button.name, Button)
+Vue.component(Form.name, Form)
+Vue.component(FormItem.name, FormItem)
+Vue.component(Input.name, Input)
+Vue.component(InputNumber.name, InputNumber)
+Vue.component(Table.name, Table)
+Vue.component(TableColumn.name, TableColumn)
+Vue.component(Upload.name, Upload)
+Vue.component(Upload.name, Upload)
+
+Vue.prototype.$message = Message;
+Vue.prototype.$loading = Loading.service;

+ 44 - 0
src/router.js

@@ -0,0 +1,44 @@
+import Vue from 'vue'
+import Router from 'vue-router'
+import Home from './views/Home'
+import Message from './views/Message'
+import Console from './views/Console'
+import Auth from './views/Auth'
+import Error from './views/Error'
+
+Vue.use(Router)
+
+export default new Router({
+    routes: [
+    {
+        path: '/show',
+        name: 'home',
+        component: Home
+    },
+    {
+        path: '/message',
+        name: 'message',
+        component: Message
+    },
+    {
+        path: '/console',
+        name: 'console',
+        component: Console
+    },{
+        path: '/',
+        name: 'auth',
+        component: Auth
+    },{
+        path: '/error',
+        name: 'error',
+        component: Error
+    }],
+    scrollBehavior: () => ({ y: 0 })
+})
+
+/**
+ * 权限路由
+ */
+export const authRouterMap = [
+
+]

+ 16 - 0
src/store.js

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

+ 3 - 0
src/utils/bus.js

@@ -0,0 +1,3 @@
+import Vue from "vue";
+
+export default new Vue()

+ 16 - 0
src/utils/http.js

@@ -0,0 +1,16 @@
+import qs from 'qs'
+import axios from 'axios'
+
+axios.defaults.baseURL = process.env.VUE_APP_BASEAPI+'/api/'
+
+const post = axios.post
+
+axios.post = function(url,data={}){
+    data = qs.stringify(data)
+    return post(url,data)
+}
+axios.file = function(...arg){
+    return post(...arg)
+}
+
+export default axios

+ 52 - 0
src/views/Auth/index.vue

@@ -0,0 +1,52 @@
+<template>
+    <div style="padding:20px">
+        {{msg}}
+    </div>
+</template>
+<script>
+import Cookie from 'js-cookie'
+export default {
+    data() {
+        return {
+            msg: '跳转中...'
+        }
+    },
+    created() {
+        const query = {}
+        const search = location.search.substr(1).split('&') || []
+        search.forEach(item => {
+            if (!item) {
+                return;
+            }
+            const qs = item.split('=')
+            if (qs.length == 2) {
+                query[qs[0]] = qs[1]
+            }
+        })
+
+        if (query['code'] && query['state'] == 'ilawpark') {
+            this.$http.post('user/saveUserInfo', {
+                code: query['code']
+            }).then(result => {
+                if (result.data.code == 0) {
+                    Cookie.set('openid', result.data.data.openid)
+                    let key = Cookie.get('key') || ''
+                    return this.$router.replace({
+                        name: 'message',
+                        query: {
+                            key: key
+                        }
+                    })
+
+                } else {
+                    this.msg = '授权失败,请重试'
+                }
+            }).catch(() => {
+                this.msg = '服务器连接失败,请重试'
+            })
+        } else {
+            location.href = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxb8a54b366d1b05c2&redirect_uri=http%3A%2F%2Filawpark.4dage.com&response_type=code&scope=snsapi_userinfo&state=ilawpark#wechat_redirect'
+        }
+    }
+}
+</script>

+ 64 - 0
src/views/Cart/index.vue

@@ -0,0 +1,64 @@
+<template>
+    <section class="max-width">
+        <el-table :data="tableData" style="width: 100%">
+            <el-table-column type="selection" width="55"></el-table-column>
+            <el-table-column label="日期" width="180">
+                <template slot-scope="scope">
+                    <i class="el-icon-time"></i>
+                    <span style="margin-left: 10px">{{ scope.row.date }}</span>
+                </template>
+            </el-table-column>
+            <el-table-column label="姓名" width="180">
+                <template slot-scope="scope">
+                    <el-popover trigger="hover" placement="top">
+                        <p>姓名: {{ scope.row.name }}</p>
+                        <p>住址: {{ scope.row.address }}</p>
+                    </el-popover>
+                </template>
+            </el-table-column>
+            <el-table-column label="操作">
+                <template slot-scope="scope">
+                    <el-button size="mini" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
+                    <el-button size="mini" type="danger" @click="handleDelete(scope.$index, scope.row)">删除</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+    </section>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+            tableData: [{
+                date: '2016-05-02',
+                name: '王小虎',
+                address: '上海市普陀区金沙江路 1518 弄'
+            }, {
+                date: '2016-05-04',
+                name: '王小虎',
+                address: '上海市普陀区金沙江路 1517 弄'
+            }, {
+                date: '2016-05-01',
+                name: '王小虎',
+                address: '上海市普陀区金沙江路 1519 弄'
+            }, {
+                date: '2016-05-03',
+                name: '王小虎',
+                address: '上海市普陀区金沙江路 1516 弄'
+            }].filter(item => {
+                item.check = false
+                return true;
+            })
+        }
+    },
+    methods: {
+        handleEdit(index, row) {
+            console.log(index, row);
+        },
+        handleDelete(index, row) {
+            console.log(index, row);
+        }
+    }
+}
+</script>

+ 289 - 0
src/views/Console/components/Comments.vue

@@ -0,0 +1,289 @@
+<template>
+    <div class="com-comments">
+        <div class="com-comments-header">
+            <!-- <span><el-button type="primary" size="mini" @click="onSwitch" :loading="loading.switch">切屏</el-button></span> -->
+            <span>显示留言&nbsp;<el-switch v-model="power" active-color="#13ce66" @change="onSwitch"></el-switch></span>
+            <span>人工审核&nbsp;<el-switch v-model="handler" active-color="#13ce66" @change="onHandler"></el-switch></span>
+        </div>
+        <el-table :data="tableData" style="width: 100%">
+            <el-table-column label="留言">
+                <template slot-scope="scope">
+                    <div style="padding-bottom:5px">
+                        <span>时间:{{scope.row.createTime}}</span>
+                        <span style="float:right">
+                            <el-tag  size="mini" :type="messageState.status[scope.row.showStatus]">{{messageState.text[scope.row.showStatus]}}</el-tag>
+                        </span>
+                    </div>
+                    <div style="text-align:right;padding:5px 0">
+                        <el-button size="mini" @click="onMessageDetail(scope.row)">查看</el-button>
+                        <el-button size="mini" v-if="scope.row.showStatus==0" type="danger" @click="onMessageHandle(scope.row,-1)">拒绝</el-button>
+                        <el-button size="mini" v-if="scope.row.showStatus==0" type="success" @click="onMessageHandle(scope.row,1)">通过</el-button>
+                    </div>
+                </template>
+            </el-table-column>
+        </el-table>
+    </div>
+</template>
+<script>
+let worker
+export default {
+    data() {
+        return {
+            power: true,
+            handler: false,
+            loading: {
+                switch: false
+            },
+            messageState: {
+                status: {
+                    "0": 'info',
+                    "1": 'success',
+                    "-1": 'danger'
+                },
+                text: {
+                    "0": '未处理',
+                    "1": '已通过',
+                    "-1": '已拒绝'
+                }
+            },
+            tableData: []
+        }
+    },
+    created() {
+        this.load(()=>{
+             this.$bus.$emit('size-refresh')
+        })
+        this.$http.post('manager/getModeDetail').then(result => {
+            if (result.data.code == 0) {
+                this.handler = result.data.data.status == 0 ? true : false
+            }
+        })
+        this.$http.post('manager/getScreenDetail').then(result => {
+            if (result.data.code == 0) {
+                this.power = result.data.data.screenStatus == 0
+            }
+        })
+
+        worker = new Worker('static/worker.comments.js')
+        worker.onmessage = (e) => {
+            if (e.data.cmd == 'list') {
+                this.load()
+            }
+        }
+    },
+    destroyed() {
+        worker && worker.terminate()
+    },
+    methods: {
+        load(fn) {
+            this.$http.post('comment/list').then(result => {
+                if (result.data.code == 0) {
+                    this.tableData = result.data.data
+                    fn && this.$nextTick(fn)
+                }
+            })
+        },
+        /**
+         * 切屏
+         */
+        onSwitch() {
+            this.$http.post('manager/switchScreen', {
+                status: this.power ? 0 : 1
+            }).then(result => {
+                if (result.data.code == -1) {
+                    this.power = !this.power
+                    this.$message({
+                        message: `${this.power?'开始':'关闭'}展示留言失败`,
+                        type: 'error'
+                    });
+                } else {
+                    this.$message({
+                        message: `${this.power?'开始':'关闭'}展示留言成功`,
+                        type: 'success'
+                    });
+                }
+            }).catch(err => {
+                this.power = !this.power
+                this.$message({
+                    message: `${this.power?'开始':'关闭'}展示留言失败`,
+                    type: 'error'
+                });
+            })
+        },
+        /**
+         * 审核状态切换
+         */
+        onHandler() {
+            this.$http.post('manager/switchMode', {
+                status: this.handler ? 0 : 1
+            }).then(result => {
+                if (result.data.code == -1) {
+                    this.handler = !this.handler
+                    this.$message({
+                        message: '审核方式切换失败',
+                        type: 'error'
+                    });
+                } else {
+                    this.$message({
+                        message: '审核方式切换成功',
+                        type: 'success'
+                    });
+                }
+            }).catch(err => {
+                this.handler = !this.handler
+                this.$message({
+                    message: '审核方式切换失败',
+                    type: 'error'
+                });
+            })
+        },
+        /**
+         * 查看留言
+         */
+        onMessageDetail(row) {
+            this.$http.post('comment/detail', {
+                commentId: row.id
+            }).then(result => {
+                if (result.data.code == -1) {
+                    this.$message({
+                        message: result.data.msg,
+                        type: 'error'
+                    });
+                } else {
+                    //process.env.VUE_APP_BASEAPI+
+                    const data = result.data.data
+                    const div = document.createElement('div')
+                    div.onclick = function() {
+                        document.body.removeChild(div)
+                    }
+                    div.className = 'com-comments-viewer'
+                    div.innerHTML = [
+                        `<div class="viewer-word">${this.getWord(data)}</div>`,
+                        `<div class="viewer-pics" style="${(data.url ? 'background-image:url(' + (data.url) + ')' : '')}">`,
+                        `   ${(data.url ? '' : '<span>无用户自拍照</span>')}`,
+                        `</div>`
+                    ].join('')
+
+                    document.body.appendChild(div)
+
+                    if (data.comment && data.commentType == 'draw') {
+                        this.canvas = document.querySelector('.com-comments-viewer canvas')
+                        this.canvas.width = window.innerWidth
+                        this.canvas.height = window.innerHeight / 2
+                        this.context = this.canvas.getContext("2d");
+                        this.draw(JSON.parse(data.comment).data)
+                    }
+                }
+            }).catch(err => {
+                console.error(err)
+                this.$message({
+                    message: '请求失败',
+                    type: 'error'
+                });
+            })
+        },
+        /**
+         * 处理留言
+         */
+        onMessageHandle(row, state) {
+            this.$http.post('manager/updateComment', {
+                showStatus: state,
+                commentId: row.id
+            }).then(result => {
+                if (result.data.code == -1) {
+                    row.showStatus = state
+                    this.$message({
+                        message: result.data.msg,
+                        type: 'error'
+                    });
+                } else {
+                    this.$message({
+                        message: result.data.msg,
+                        type: 'success'
+                    });
+                }
+            }).catch(err => {
+                this.$message({
+                    message: result.data.msg,
+                    type: 'error'
+                });
+            })
+        },
+        draw(data, i = 0) {
+            i++;
+            if (i < data.length - 1 && data[i].t) {
+                setTimeout(() => {
+                    this.context.beginPath()
+                    this.context.moveTo(data[i].x, data[i].y)
+                    this.context.lineTo(data[i + 1].x, data[i + 1].y)
+                    this.context.lineWidth = data[i].width;
+                    this.context.lineCap = "round"
+                    this.context.linJoin = "round"
+                    this.context.stroke();
+
+                    this.draw(data, i)
+                }, data[i].t > 200 ? 200 : data[i].t)
+            } else if (i < data.length - 1) {
+                this.draw(data, i)
+            }
+        },
+        getWord(data) {
+            if (!data.comment) {
+                return '<span>无留言</span>'
+            } else if (data.commentType == 'draw') {
+                return `<canvas width="${window.innerWidth}" height = "${window.innerHeight/2}"> </canvas>`
+            } else {
+                return `<div>${data.comment}</div>`
+            }
+        }
+
+    }
+}
+</script>
+<style lang="less" scoped>
+.com-comments-header {
+    display: flex;
+    justify-content: space-between;
+    font-size: 16px;
+}
+</style>
+<style lang="less">
+.com-comments-viewer {
+    position: fixed;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 100%;
+    background: #fff;
+    z-index: 1000;
+
+    .viewer-word {
+        height: 50%;
+        background: #efefef;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        font-size:42px;
+
+        canvas {
+            width: 100%;
+            height: 100%;
+        }
+
+        div {
+            padding: 10px;
+        }
+
+    }
+
+    .viewer-pics {
+        height: 50%;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        background-size: contain;
+        background-position: center center;
+        background-repeat: no-repeat
+    }
+}
+</style>

+ 290 - 0
src/views/Console/components/FileUpload.vue

@@ -0,0 +1,290 @@
+<template>
+    <div class="com-files">
+        <el-upload ref="uploader" multiple accept="image/jpg, image/jpeg,video/mp4" :action="action" :limit="30" :on-success="onSuccess" :on-error="onError" :before-upload="beforeUpload" :on-exceed="handleExceed" :http-request="httpRequest">
+            <el-button size="small" type="primary">点击上传</el-button>
+            <div slot="tip" class="el-upload__tip">只能上传JPG/MP4文件,最多30个文件</div>
+        </el-upload>
+        <ul class="file-list">
+            <li v-for="(item,i) in fileList" :key="i">
+                <i class="el-icon-caret-right" title="播放当前背景" @click="onPlay(item.id)"></i>
+                <a href="javascript:;" @click="handlePreview(item.url)">
+                    <!-- <i class="el-icon-zoom-in"></i> -->
+                    {{item.name}}
+                </a>
+                <template v-if="item.type == 'video'">
+                    <el-upload class="upload-gif" accept="image/gif" :action="actionGIF" :http-request="httpRequestGIF" :multiple="false" :on-error="onError" :data="{bannerId:item.id}">
+                        <i class="el-icon-picture" title="上传视频封面图"></i>
+                    </el-upload>
+                </template>
+
+                <i class="el-icon-close" @click="onDelete(item.id)" title="删除"></i>
+            </li>
+        </ul>
+    </div>
+</template>
+<script>
+export default {
+    data() {
+        return {
+            fileList: [],
+            action: 'manager/uploadFile',
+            actionGIF: 'manager/uploadGif'
+        };
+    },
+    created() {
+        this.loadList()
+    },
+    methods: {
+        loadList(timeout = 500) {
+            const loading = this.$loading({
+                lock: true,
+                text: '数据加载中...',
+                spinner: 'el-icon-loading',
+                background: 'rgba(255, 255, 255, 0.92)'
+            });
+            setTimeout(() => {
+                this.$http.post('banner/list').then(result => {
+                    if (result.data.code == 0) {
+                        loading.close()
+                        //process.env.VUE_APP_BASEAPI +
+                        this.fileList = result.data.data.map(item => {
+                            return {
+                                id: item.id,
+                                name: item.fileName,
+                                type: /\.mp4$/i.test(item.url) ? 'video' : 'image',
+                                url:  item.url
+                            }
+                        })
+                        this.$nextTick(() => {
+                            this.$bus.$emit('size-refresh')
+                        })
+                    }
+                })
+            }, timeout);
+        },
+        onPlay(id) {
+            this.$http.post('manager/switchBg', {
+                status: 1,
+                bannerId: id
+            }).then(result => {
+                if (result.data.code == 0) {
+                    this.$message({
+                        message: '切换背景成功',
+                        type: 'success'
+                    });
+                } else {
+                    this.$message({
+                        message: '切换背景失败',
+                        type: 'error'
+                    });
+                }
+            }).catch(() => {
+                this.$message({
+                    message: '切换背景失败',
+                    type: 'error'
+                });
+            })
+        },
+        onDelete(id) {
+            this.$http.post('banner/remove', {
+                bannerId: id
+            }).then(result => {
+                if (result.data.code == 0) {
+                    this.loadList()
+                } else {
+                    this.$message({
+                        message: '删除失败',
+                        type: 'error'
+                    });
+                }
+            }).catch(err => {
+                this.submiting = false
+                this.$message({
+                    message: '删除失败',
+                    type: 'error'
+                });
+            })
+        },
+        onSuccess(e) {
+            this.$refs.uploader.clearFiles()
+            this.loadList()
+        },
+        onError() {
+            this.$message({
+                message: '上传失败',
+                type: 'error'
+            });
+        },
+        handlePreview(src) {
+            const div = document.createElement('div')
+            div.className = 'file-preview'
+            div.onclick = function() {
+                document.body.removeChild(div)
+            }
+            document.body.appendChild(div)
+
+            if (/\.mp4$/i.test(src)) {
+                div.innerHTML = [
+                    '<video id="video" name="media" controls crossorigin="anonymous">',
+                    '<source src="' + src + '" type="video/mp4">',
+                    '</video>'
+                ].join('')
+            } else {
+                div.innerHTML = '<div class="img" style="background-image:url(' + src + ')" ></div>'
+            }
+        },
+        handleExceed(files, fileList) {
+            console.log(`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
+        },
+        beforeUpload(file) {
+            if (/(\.jpg|\.jpeg|\.mp4)$/i.test(file.name)) {
+                return true
+            }
+            return false
+        },
+        httpRequest(config) {
+            const form = new FormData()
+            form.append(config.filename, config.file)
+            this.$http.file(config.action, form, {
+                onUploadProgress: function(e) {
+                    if (e.total > 0) {
+                        e.percent = e.loaded / e.total * 100;
+                    }
+                    config.onProgress(e)
+                }
+            }).then(response => {
+                if (response.data.code == 0) {
+                    config.onSuccess(response)
+                } else {
+                    config.onError(error)
+                }
+            }).catch(error => {
+                config.onError(error)
+            })
+        },
+        httpRequestGIF(config) {
+            const reader = new FileReader()
+            reader.readAsDataURL(config.file)
+            reader.onload = () => {
+                config.data.base64Data = reader.result
+                this.$http.post(config.action, config.data).then(response => {
+                    if (response.data.code == 0) {
+                        this.$message({
+                            message: '上传封面图成功',
+                            type: 'success'
+                        });
+                    } else {
+                        config.onError(error)
+                    }
+                }).catch(error => {
+                    config.onError(error)
+                })
+            }
+        }
+    }
+}
+</script>
+<style lang="less" scoped>
+.file-list {
+    list-style: none;
+
+    li {
+        margin-top: 10px;
+        font-size: 14px;
+        color: #606266;
+        line-height: 1.8;
+        position: relative;
+        border-radius: 4px;
+        width: 100%;
+    }
+
+    a {
+        cursor: pointer;
+        color: #606266;
+        display: block;
+        margin-right: 50px;
+        margin-left: 20px;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+
+        &:focus {
+            color: #f60;
+        }
+    }
+
+    i.el-icon-caret-right {
+        position: absolute;
+        top: 5px;
+        left: 0px;
+        cursor: pointer;
+        opacity: .75;
+        color: #606266;
+    }
+
+    i.el-icon-zoom-in {
+        height: 100%;
+        margin-right: 7px;
+        color: #909399;
+        line-height: inherit;
+    }
+
+    i.el-icon-close {
+        position: absolute;
+        top: 5px;
+        right: 5px;
+        cursor: pointer;
+        opacity: .75;
+        color: #606266;
+    }
+
+    i.el-icon-picture {
+        cursor: pointer;
+        opacity: .75;
+        color: #606266;
+    }
+
+    .upload-gif {
+        position: absolute;
+        top: 0px;
+        right: 26px;
+    }
+}
+</style>
+<style lang="less">
+.file-preview {
+    position: fixed;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    top: 0;
+    left: 0;
+    bottom: 0;
+    right: 0;
+    background-color: rgba(0, 0, 0, 0.5);
+    overflow: hidden;
+    z-index: 10000;
+
+    div.img {
+        width: 100%;
+        height: 100%;
+        background-size: contain;
+        background-position: center center;
+        background-repeat: no-repeat
+    }
+
+    video {
+        display: flex;
+        width: 80%;
+        height: 80;
+
+    }
+
+}
+
+.upload-gif {
+    .el-upload-list {
+        display: none !important;
+    }
+}
+</style>

+ 75 - 0
src/views/Console/components/Setting.vue

@@ -0,0 +1,75 @@
+<template>
+    <el-form ref="form" label-position="top" :model="form" class="com-setting" v-show="loaded">
+        <el-form-item label="图片轮播时间(秒)">
+            <el-input-number v-model="form.delay" style="width:100%" :min="5"></el-input-number>
+        </el-form-item>
+        <el-form-item label="留言展示切换倒数(秒)">
+            <el-input-number v-model="form.countDown" style="width:100%" :min="5"></el-input-number>
+        </el-form-item>
+        <el-form-item style="text-align:center">
+            <el-button type="primary" size="small" @click="onSubmit" :loading="submiting">保存</el-button>
+        </el-form-item>
+    </el-form>
+</template>
+<script>
+export default {
+    data() {
+        return {
+            form: {
+                delay: 30,
+                countDown: 10,
+            },
+            loaded:false,
+            submiting: false,
+        }
+    },
+    created() {
+        const loading = this.$loading({
+            lock: true,
+            text: '数据加载中...',
+            spinner: 'el-icon-loading',
+            background: 'rgba(255, 255, 255, 0.92)'
+        });
+        setTimeout(() => {
+            this.$http.post('manager/getTimeDetail').then(result => {
+                if (result.data.code == 0) {
+                    loading.close()
+                    this.loaded = true
+                    this.form.delay = result.data.data.img
+                    this.form.countDown = result.data.data.comment
+                }
+            })
+        }, 500);
+
+    },
+    methods: {
+        onSubmit() {
+            this.status = ''
+            this.submiting = true
+            this.$http.post('manager/saveTime', {
+                imgTime: this.form.delay,
+                commentTime: this.form.countDown
+            }).then(result => {
+                this.submiting = false
+                if (result.data.code == -1) {
+                    this.$message({
+                        message: '保存失败',
+                        type: 'error'
+                    });
+                } else {
+                    this.$message({
+                        message: '保存成功',
+                        type: 'success'
+                    });
+                }
+            }).catch(err => {
+                this.submiting = false
+                this.$message({
+                    message: '保存失败',
+                    type: 'error'
+                });
+            })
+        }
+    }
+}
+</script>

+ 94 - 0
src/views/Console/index.vue

@@ -0,0 +1,94 @@
+<template>
+    <div class="console-review">
+        <el-tabs type="border-card" :stretch="true" @tab-click="change" class="console-review-tabs">
+            <el-tab-pane label="留言审核" lazy>
+                <comments></comments>
+            </el-tab-pane>
+            <el-tab-pane label="系统设置" lazy>
+                <setting></setting>
+            </el-tab-pane>
+            <el-tab-pane label="文件管理" lazy>
+                <file-upload></file-upload>
+            </el-tab-pane>
+        </el-tabs>
+    </div>
+</template>
+<script>
+import Comments from './components/Comments.vue'
+import Setting from './components/Setting.vue'
+import FileUpload from './components/FileUpload.vue'
+let jroll
+
+function resize() {
+    const $header = this.$el.querySelector('.el-tabs__header')
+    if ($header) {
+        const height = window.innerHeight - $header.clientHeight
+        this.$el.querySelector(".el-tabs__content").style.height = height + 'px'
+    }
+}
+export default {
+    components: {
+        FileUpload,
+        Comments,
+        Setting
+    },
+    data() {
+        return {
+            isViewComments:false
+        }
+    },
+    created() {
+        window.addEventListener('resize', () => {
+            resize.call(this)
+        }, false)
+
+        this.$bus.$on('size-refresh', this.refresh)
+    },
+    destroyed() {
+        window.removeEventListener('resize', resize)
+    },
+    mounted() {
+        this.$nextTick(() => {
+            resize.call(this)
+            jroll = new JRoll(this.$el.querySelector(".el-tabs__content"), { scrollBarY: true, bounce: false });
+        })
+    },
+    methods: {
+        refresh() {
+            setTimeout(() => {
+                jroll.refresh()
+                jroll.scrollTo(0, 0);
+            }, 16);
+        },
+        change(tab) {
+            jroll.scrollTo(0, 0);
+            jroll.destroy()
+            this.$nextTick(() => {
+                jroll = new JRoll(this.$el.querySelector(".el-tabs__content"), {
+                    id: tab.$el.getAttribute('id'),
+                    scroller: tab.$el,
+                    scrollBarY: false,
+                    bounce: false
+                });
+
+                this.refresh()
+
+            })
+
+        }
+    }
+}
+</script>
+<style lang="less" scoped>
+.console-review{
+    width: 100%;
+    height: 100%;
+}
+</style>
+
+<style lang="less">
+.console-review-tabs {
+    box-shadow: none !important;
+    border: none !important;
+}
+</style>

+ 19 - 0
src/views/Error/index.vue

@@ -0,0 +1,19 @@
+<template>
+    <div style="padding:10px;font-size:14px">{{msg}}</div>
+</template>
+<script>
+export default {
+    data(){
+        return {
+            msg:''
+        }
+    },
+    created(){
+        const statusCode = this.$route.query.code
+        if(statusCode == 401){
+            this.msg = '二维码已失效,请重新扫描操作'
+        }
+    }
+}
+</script>
+

+ 58 - 0
src/views/Fonts/index.vue

@@ -0,0 +1,58 @@
+<template>
+    <div>
+        <ul>
+            <li v-for="(item,i) in fonts" :key="i">
+                <p :style="{'font-family':item.en}">{{item.ch+':'+isSupportFontFamily(item.en)}}</p>
+            </li>
+        </ul>
+    </div>
+</template>
+<script>
+import Fonts from '@/config/fonts'
+export default {
+    data() {
+        return {
+            fonts: Fonts['office']
+        }
+    },
+    methods: {
+        isSupportFontFamily() {
+            //    f是要检测的字体
+            if (typeof f != "string") {
+                return false
+            }
+            //    h是基础字体
+            var h = "Arial";
+            if (f.toLowerCase() == h.toLowerCase()) {
+                return true
+            }
+            //    设置一个检测的字符A,看他是否支持f字体
+            var e = "a";
+            var d = 100;
+            var a = 100,
+                i = 100;
+            var c = document.createElement("canvas");
+            var b = c.getContext("2d");
+            c.width = a;
+            c.height = i;
+            b.textAlign = "center";
+            b.fillStyle = "black";
+            b.textBaseline = "middle";
+            var g = function(j) {
+                b.clearRect(0, 0, a, i);
+                //        字体是传入的j,或者是默认的h
+                b.font = d + "px " + j + ", " + h;
+                b.fillText(e, a / 2, i / 2);
+                //        获取所有的canvas图片信息
+                var k = b.getImageData(0, 0, a, i).data;
+                //        k调用数组的 filter方法,筛选符合条件的。改变原数组。
+                return [].slice.call(k).filter(function(l) {
+                    return l != 0
+                });
+            };
+            //    返回结果,如果h默认字体和输入待检测字体f.通过g函数检测得到的字符串不一致,说明自提生效
+            return g(h).join("") !== g(f).join("");
+        }
+    }
+}
+</script>

+ 71 - 0
src/views/Home/components/QrCode.vue

@@ -0,0 +1,71 @@
+<template>
+    <div class="com-qrcode">
+        <img v-show="codeSrc" :src="codeSrc">
+        <div class="tips">
+            扫一扫上方二维码<br>
+            在手机端更改文字<br>
+            及图片、视频信息。
+        </div>
+        </div>
+</template>
+<script>
+export default {
+    props: {
+        comment: Object
+    },
+    watch: {
+        comment() {
+            if (typeof __CAPTURE != 'undefined' && this.comment) {
+                __CAPTURE.remote.getCurrentWebContents().capturePage((capture) => {
+                    this.$http.post('comment/uploadScreen', {
+                        commentId: this.comment.id,
+                        base64Data: capture.toDataURL()
+                    })
+                })
+            }
+        }
+    },
+    data() {
+        return {
+            codeSrc: ''
+        }
+    },
+    created() {
+        this.getQrCode()
+        setInterval(() => {
+            this.getQrCode()
+        }, 1000 * 60 * 3); // 3分钟获取一次新的二维码
+    },
+    methods: {
+        getQrCode() {
+            this.$http.post('banner/createQrCode').then(result => {
+                if (result.data.code == 0) {
+                    this.codeSrc = process.env.VUE_APP_BASEAPI + result.data.data.qrcode
+                }
+            })
+        }
+    }
+}
+</script>
+
+<style lang="less" scoped>
+.com-qrcode {
+    position: absolute;
+    top: 443px;
+    left: 110px;
+
+    img {
+        width: 300px;
+        height: 300px;
+        background: #fff;
+        padding: 12px;
+    }
+
+    .tips {
+        margin-top: 67px;
+        color: #fff;
+        font-size: 36px;
+        line-height: 1.7;
+    }
+}
+</style>

+ 70 - 0
src/views/Home/components/UserDraw.vue

@@ -0,0 +1,70 @@
+<template>
+    <div class="com-user-draw">
+        <canvas></canvas>
+    </div>
+</template>
+<script>
+export default {
+    props: {
+        comment: Object
+    },
+    data() {
+        return {
+            codeSrc: ''
+        }
+    },
+    mounted() {
+        this.words = JSON.parse(this.comment.comment)
+        this.canvas = this.$el.querySelector('canvas')
+        this.context = this.canvas.getContext("2d");
+        // this.canvas.width = this.words.viewport.width
+        // this.canvas.height = this.words.viewport.height
+        this.canvas.width = this.$el.clientWidth
+        this.canvas.height = this.$el.clientHeight
+        this.ratioX = this.canvas.width / this.words.viewport.width;
+        this.ratioY = this.canvas.height / this.words.viewport.height;
+        this.draw()
+    },
+    methods: {
+        draw(i = 0) {
+            i++;
+            if (i < this.words.data.length - 1 && this.words.data[i].t) {
+                setTimeout(() => {
+
+                    this.context.beginPath()
+                    this.context.moveTo(this.words.data[i].x * this.ratioX, this.words.data[i].y * this.ratioY)
+                    this.context.lineTo(this.words.data[i + 1].x * this.ratioX, this.words.data[i + 1].y * this.ratioY)
+                    this.context.lineWidth = this.words.data[i].width * this.ratioX;
+                    this.context.lineCap = "round"
+                    this.context.linJoin = "round"
+                    this.context.strokeStyle = '#ffffff';
+                    this.context.stroke();
+
+                    this.draw(i)
+                }, this.words.data[i].t > 200 ? 200 : this.words.data[i].t)
+            } else if (i < this.words.data.length - 1) {
+                this.draw(i)
+            } else if (i == this.words.data.length - 1) {
+                if (typeof __CAPTURE != 'undefined') {
+                    __CAPTURE.remote.getCurrentWebContents().capturePage((capture) => {
+                        this.$http.post('comment/uploadScreen', {
+                            commentId: this.comment.id,
+                            base64Data: capture.toDataURL()
+                        })
+                    })
+                }
+            }
+        },
+    }
+}
+</script>
+
+<style lang="less" scoped>
+.com-user-draw {
+    position: absolute;
+    top: 585px;
+    left: 108px;
+    width: 540px;
+    height: 400px;
+}
+</style>

+ 35 - 0
src/views/Home/components/UserText.vue

@@ -0,0 +1,35 @@
+<template>
+    <div class="com-user-text" v-html="comment.comment"></div>
+</template>
+<script>
+export default {
+    props: {
+        comment: Object
+    },
+    mounted() {
+        this.$nextTick(() => {
+            if (typeof __CAPTURE != 'undefined') {
+                __CAPTURE.remote.getCurrentWebContents().capturePage((capture) => {
+                    this.$http.post('comment/uploadScreen', {
+                        commentId: this.comment.id,
+                        base64Data: capture.toDataURL()
+                    })
+                })
+            }
+        })
+    }
+}
+</script>
+
+<style lang="less" scoped>
+.com-user-text {
+    position: absolute;
+    top: 585px;
+    left: 108px;
+    width: 570px;
+    height: 400px;
+    line-height: 1.2;
+    font-size: 60px;
+    color: #fff;
+}
+</style>

+ 396 - 0
src/views/Home/index.vue

@@ -0,0 +1,396 @@
+<template>
+    <div class="home">
+        <div class="side">
+            <component :is="sideComponentName" :comment="comment"></component>
+        </div>
+        <div class="main">
+            <div class="swiper-container">
+                <div class="swiper-wrapper">
+                    <div class="swiper-slide" v-for="item in banners" :key="item.id">
+                        <img  v-if="item.type == 'image'" :src="item.url">
+                        <div v-else>
+                            <video autoplay="" loop crossorigin="anonymous">
+                                <source :src="item.url" type="video/mp4">
+                            </video>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div v-if="comment && comment.url" class="show-banner">
+                <template v-if="comment.type == 'image'">
+                    <div v-if="comment.photo">
+                        <div class="photo" :style="{'background-image':`url(${comment.photo})`}"></div>
+                        <video autoplay="" loop crossorigin="anonymous">
+                            <source :src="comment.url" type="video/mp4">
+                        </video>
+                    </div>
+                    <img v-else :src="comment.url">
+                </template>
+                    <div v-else>
+                        <video autoplay="" loop crossorigin="anonymous">
+                        <source :src="comment.url" type="video/mp4">
+                    </video>
+                    </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import QrCode from './components/QrCode'
+import UserDraw from './components/UserDraw'
+import UserText from './components/UserText'
+let swiper;
+let isShow = true;
+let bannerTimer;
+
+function waitForSwitch() {
+    setTimeout(() => {
+        this.$http.post('manager/getScreenDetail').then(result => {
+            if (result.data.code == 0) {
+                if (result.data.data.screenStatus == 1) {
+                    if (isShow == true) {
+                        isShow = false;
+                        showComment.__timer && clearTimeout(showComment.__timer)
+                        this.comment = null
+                    }
+                } else {
+                    if (isShow == false) {
+                        isShow = true
+                        showComment.call(this)
+                    }
+                }
+
+                if (result.data.data.bgStatus == 1) {
+                    const bannerId = result.data.data.bgBannerId
+                    this.$http.post('manager/switchBg', {
+                        status: 0,
+                        bannerId: bannerId
+                    })
+
+                    let index = -1
+                    this.banners.forEach((item, i) => {
+                        if (item.id == bannerId) {
+                            index = i
+                        }
+                    });
+                    if (index !== -1 && swiper) {
+                        this.bannerSwitch(index, false, true)
+                    }
+                }
+            }
+            waitForSwitch.call(this)
+        }).catch(() => {
+            waitForSwitch.call(this)
+        })
+    }, 2000);
+}
+
+function waitForSetting(init) {
+    if (init) {
+        this.$http.post('manager/getTimeDetail').then(result => {
+            if (result.data.code == 0) {
+                this.setting.img = parseInt(result.data.data.img) * 1000
+                this.setting.comment = parseInt(result.data.data.comment) * 1000
+            }
+        })
+    }
+    setTimeout(() => {
+        this.$http.post('manager/getTimeDetail').then(result => {
+            if (result.data.code == 0) {
+                this.setting.img = parseInt(result.data.data.img) * 1000
+                this.setting.comment = parseInt(result.data.data.comment) * 1000
+            }
+            waitForSetting.call(this)
+        }).catch(() => {
+            waitForSetting.call(this)
+        })
+    }, 3000);
+}
+
+function getComments() {
+    setTimeout(() => {
+        if(!isShow){
+            return
+        }
+        if (this.comments.length) {
+            getComments.call(this)
+        } else {
+            this.$http.post('comment/getUnplayList').then(result => {
+                if (result.data.code == 0) {
+                    this.comments = result.data.data
+                    showComment.call(this)
+                }
+            }).catch(() => {
+                getComments.call(this)
+            })
+        }
+    }, 3000);
+}
+
+function showComment() {
+
+    this.$nextTick(() => {
+        const comment = this.comments.shift()
+
+        if (comment) {
+            if (!comment.url && comment.bannerId) {
+                const find = this.banners.filter(item => item.id == comment.bannerId)
+                if (find.length) {
+                    comment.url = find[0].url
+                }
+            } else if (comment.url) {
+                //process.env.VUE_APP_BASEAPI +
+                //comment.url =  comment.url
+            }
+
+            comment.type = /\.mp4$/.test(comment.url) ? 'video' : 'image';
+
+            if (comment.url && !comment.bannerId) {
+                let img = new Image()
+                img.src = comment.url
+                img.onload = () => {
+                    if (img.width < img.height) {
+                        comment.photo = comment.url
+                        comment.url = this.banners.filter(item => /\.mp4$/.test(item.url))[0].url
+                    }
+                    this.showComment(comment)
+                }
+                img.onerror = () => {
+                    this.showComment(comment)
+                }
+            } else {
+                this.showComment(comment)
+            }
+
+            this.$http.post('comment/updateStatus', { commentId: comment.id, playStatus: 1 })
+
+            showComment.__timer = setTimeout(() => {
+                this.comment = null
+                showComment.call(this)
+            }, this.setting.comment);
+        } else {
+            getComments.call(this)
+        }
+    })
+}
+export default {
+    name: "Home",
+    components: {
+        QrCode,
+        UserDraw,
+        UserText
+    },
+    data() {
+        return {
+            comment: null,
+            banners: [],
+            comments: [],
+            setting: {
+                img: 30000,
+                comment: 30000
+            }
+        }
+    },
+    computed: {
+        sideComponentName() {
+            if (!this.comment || !this.comment.comment) {
+                return 'QrCode'
+            }
+            if (this.comment.commentType == 'text') {
+                return 'UserText'
+            } else {
+                return 'UserDraw'
+            }
+        }
+    },
+    created() {
+        this.loadBanners()
+        getComments.call(this)
+        waitForSwitch.call(this)
+        waitForSetting.call(this, true)
+    },
+    methods: {
+        loadBanners(length) {
+            //process.env.VUE_APP_BASEAPI
+            this.$http.post('banner/list').then(result => {
+                if (result.data.code == 0) {
+                    this.banners = result.data.data.map(item => {
+                        return {
+                            id: item.id,
+                            type: /\.mp4$/.test(item.url) ? 'video' : 'image',
+                            url: item.url,
+                        }
+                    })
+
+                    if (!length) {
+                        this.bannerSwitch()
+                    } else if (length != this.banners.length) {
+                        this.bannerSwitch(-1, true)
+                    }
+
+                    setTimeout(() => {
+                        this.loadBanners(this.banners.length)
+                    }, 10000);
+                }
+            })
+        },
+        bannerSwitch(index, isUpdate, isSwitch) {
+            if (isSwitch || isUpdate) {
+                bannerTimer && clearTimeout(bannerTimer)
+            }
+
+            this.$nextTick(() => {
+                if (swiper) {
+                    if (!isSwitch) {
+                        if (++index >= this.banners.length) {
+                            index = 0
+                        }
+                    }
+                    if (isUpdate) {
+                        swiper.updateSlides()
+                    }
+                    swiper.slideToLoop(index)
+                } else {
+                    index = 0
+                    swiper = new Swiper('.swiper-container', {
+                        spaceBetween: 0,
+                        loop: true
+                    });
+
+                }
+                bannerTimer = setTimeout(() => {
+                    this.bannerSwitch(index, isUpdate, false)
+                }, this.setting.img);
+            })
+        },
+        showComment(comment) {
+            this.$nextTick(() => {
+                this.comment = {
+                    id:comment.id,
+                    type: comment.type,
+                    url: comment.url,
+                    photo: comment.photo,
+                    comment: comment.comment,
+                    commentType: comment.commentType,
+                }
+            })
+        }
+    }
+};
+</script>
+<style lang="less" scoped>
+.home {
+    width: 100%;
+    height: 100%;
+    overflow: hidden;
+    user-select: none;
+}
+
+.main {
+    height: 100%;
+    background: #ccc;
+
+    .show-banner {
+        position: fixed;
+        top: 0;
+        left: 0;
+        height: 100%;
+        width: 100%;
+        z-index: 100;
+
+        img {
+            width: 100%;
+            height: 100%;
+        }
+
+        >div {
+            height: 100%;
+            width: 100%;
+        }
+
+        .photo {
+            position: absolute;
+            top: 0;
+            right: 240px;
+            height: 100%;
+            width: 745px;
+            background-position: center center;
+            background-size: contain;
+            background-repeat: no-repeat;
+            z-index: 200;
+        }
+    }
+}
+
+.side {
+    position: fixed;
+    left: 0;
+    top: 0;
+    width: 949px;
+    height: 100%;
+    background-image: url(~/static/img/bg-home.png);
+    background-size: 100% 100%;
+    background-repeat: no-repeat;
+    z-index: 1000;
+}
+
+.side-top,
+.side-message {
+    height: 50%;
+    position: relative;
+}
+
+.side-message {
+
+    .user-text,
+    .user-draw {
+        height: 100%;
+    }
+
+    canvas {
+        position: absolute;
+        top: 0;
+        left: 0;
+        width: 100%;
+        height: 100%;
+    }
+}
+</style>
+<style lang="less">
+.home {
+    .swiper-container {
+        width: 100%;
+        height: 100%;
+
+    }
+
+    .swiper-slide {
+        text-align: center;
+        font-size: 18px;
+        background: #fff;
+        display: -webkit-box;
+        display: -ms-flexbox;
+        display: -webkit-flex;
+        display: flex;
+        -webkit-box-pack: center;
+        -ms-flex-pack: center;
+        -webkit-justify-content: center;
+        justify-content: center;
+        -webkit-box-align: center;
+        -ms-flex-align: center;
+        -webkit-align-items: center;
+        align-items: center;
+
+        img {
+            width: 100%;
+            height: 100%;
+        }
+
+        >div {
+            height: 100%;
+            width: 100%;
+        }
+    }
+}
+</style>

+ 16 - 0
src/views/Message/components/Tabs.vue

@@ -0,0 +1,16 @@
+<template>
+    <ul class="com-tabs">
+        <li>手写输入</li>
+        <li>手写输入</li>
+    </ul>
+</template>
+<style lang="less" scoped>
+.com-tabs {
+    display: flex;
+    justify-content: space-between;
+    border-bottom: solid 1px #ccc;
+    li {
+        display: inline-block;
+    }
+}
+</style>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1189 - 0
src/views/Message/index.vue


+ 42 - 0
src/views/Shared/Layout.vue

@@ -0,0 +1,42 @@
+<template>
+    <div id="app">
+        <app-header></app-header>
+        <div class="app-main">
+            <transition name="fade-transform" mode="out-in">
+                <keep-alive>
+                    <router-view :key="key" />
+                </keep-alive>
+            </transition>
+        </div>
+        <app-footer></app-footer>
+    </div>
+</template>
+<script>
+import AppHeader from './components/Header'
+import AppFooter from './components/Footer'
+export default {
+    name: 'AppMain',
+    components: {
+        AppHeader,
+        AppFooter
+    },
+    computed: {
+        key() {
+            return this.$route.fullPath
+        }
+    }
+}
+</script>
+<style lang="less" src="@/assets/styles/global.less"></style>
+<style lang="less">
+#app {
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+}
+
+.app-main {
+    padding-top: @top-height;
+    flex: 1 0 auto;
+}
+</style>

+ 33 - 0
src/views/Shared/components/Footer.vue

@@ -0,0 +1,33 @@
+<template>
+    <footer class="app-footer">
+        <div class="help-list"></div>
+        <div class="copyright">
+            <section class="max-width">
+                <span>
+                    Copyright © 2018 4DAGE Co., Ltd. All rights reserved.
+                </span>
+                <span>
+                    闽ICP备11007747号-1&nbsp;&nbsp;China: +86 400-6698-025&nbsp;&nbsp;support@wanyuda.com
+                </span>
+            </section>
+        </div>
+    </footer>
+</template>
+<style lang="less">
+.app-footer {
+     flex-shrink: 0;
+    .copyright {
+
+        background-color: @color-primary;
+
+        section {
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            color: #fff;
+            height: 40px;
+            font-size: 12px;
+        }
+    }
+}
+</style>

+ 114 - 0
src/views/Shared/components/Header.vue

@@ -0,0 +1,114 @@
+<template>
+    <header class="app-header">
+        <nav>
+            <div class="links" @mouseleave="cate=null">
+                <ul>
+                    <li class="navs" v-for="item in menu" :key="item.id" @mouseenter="cate=item">
+                        <a href="">{{item.name}}</a>
+                    </li>
+                </ul>
+                <div class="menus" v-if="cate && cate.next.length">
+                    <ul>
+                        <li v-for="item in cate.next" :key="item.id">
+                            {{item.name}}
+                            <div>
+                                <a href="" v-for="item in item.next" :key="item.id">{{item.name}}</a>
+                            </div>
+                        </li>
+                    </ul>
+                </div>
+            </div>
+        </nav>
+    </header>
+</template>
+<script>
+//import menu from '@/config/menu'
+let timer
+export default {
+    data() {
+        return {
+            menu: [],
+            cate: null,
+        }
+    },
+    methods: {
+
+    }
+}
+</script>
+<style lang="less">
+.app-header {
+    position: fixed;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: @top-height;
+    background-color: #fff;
+    box-shadow: 0 0 5px #666;
+    z-index: 100;
+
+    ul {
+        list-style: none;
+    }
+
+    nav {
+        height: 100%;
+        max-width: @max-width;
+        margin: 0 auto;
+        display: flex;
+        align-items: center;
+        // justify-content: center;
+    }
+
+    .links {
+        height: 100%;
+
+        ul {
+            height: 100%;
+            display: flex;
+            align-items: center;
+        }
+
+
+        .navs {
+            display: inline-block;
+            margin-right: 20px;
+            a {
+                text-decoration: none;
+                color:#444;
+                font-size: 16px;
+                &:hover{
+                    color:@color-primary;
+                }
+            }
+        }
+    }
+
+    .menus {
+        padding-bottom: 20px;
+        position: absolute;
+        top: @top-height;
+        left: 0;
+        width: 100%;
+        background: #fff;
+        overflow: hidden;
+        border-top: solid 1px #ddd;
+        box-shadow: 0 2px 2px #ccc;
+
+        ul {
+            width: @max-width;
+            margin: 0 auto;
+            display: flex;
+            align-items: flex-start;
+        }
+
+        li {
+
+            a {
+                display: block;
+            }
+        }
+    }
+
+}
+</style>

+ 37 - 0
vue.config.js

@@ -0,0 +1,37 @@
+const path = require('path')
+
+module.exports = {
+    assetsDir: 'static',
+    baseUrl: process.env.NODE_ENV === 'production' ? '/' : '/',
+    productionSourceMap: false,
+
+    configureWebpack: {
+        externals: {
+            electron: '__electron'
+        }
+    },
+
+    chainWebpack: config => {
+        const svgRule = config.module.rule('svg')
+        svgRule.uses.clear()
+        svgRule
+            .use('svg-sprite-loader')
+            .loader('svg-sprite-loader')
+            .options({
+                symbolId: 'icon-[name]'
+            })
+    },
+
+    pluginOptions: {
+        'style-resources-loader': {
+            preProcessor: 'less',
+            patterns: [
+                path.resolve(__dirname, './src/assets/styles/_variables.less'),
+            ]
+        }
+    },
+    devServer: {
+        disableHostCheck: true,
+        port: 8088
+    }
+}