Sfoglia il codice sorgente

修改异常提示

a1140836302 2 anni fa
parent
commit
6ca1f99b81
54 ha cambiato i file con 49 aggiunte e 6475 eliminazioni
  1. 0 8
      .env.staging
  2. 0 5
      .travis.yml
  3. 0 21
      LICENSE
  4. 0 24
      jest.config.js
  5. 0 9
      jsconfig.json
  6. 0 9
      plopfile.js
  7. 0 111
      src/components/BackToTop/index.vue
  8. 0 82
      src/components/Breadcrumb/index.vue
  9. 0 155
      src/components/Charts/Keyboard.vue
  10. 0 227
      src/components/Charts/LineMarker.vue
  11. 0 271
      src/components/Charts/MixChart.vue
  12. 0 56
      src/components/Charts/mixins/resize.js
  13. 0 166
      src/components/DndList/index.vue
  14. 0 65
      src/components/DragSelect/index.vue
  15. 0 297
      src/components/Dropzone/index.vue
  16. 0 78
      src/components/ErrorLog/index.vue
  17. 0 54
      src/components/GithubCorner/index.vue
  18. 0 44
      src/components/Hamburger/index.vue
  19. 0 180
      src/components/HeaderSearch/index.vue
  20. 0 1779
      src/components/ImageCropper/index.vue
  21. 0 19
      src/components/ImageCropper/utils/data2blob.js
  22. 0 39
      src/components/ImageCropper/utils/effectRipple.js
  23. 0 232
      src/components/ImageCropper/utils/language.js
  24. 0 7
      src/components/ImageCropper/utils/mimes.js
  25. 0 77
      src/components/JsonEditor/index.vue
  26. 0 99
      src/components/Kanban/index.vue
  27. 0 360
      src/components/MDinput/index.vue
  28. 0 31
      src/components/MarkdownEditor/default-options.js
  29. 0 118
      src/components/MarkdownEditor/index.vue
  30. 0 101
      src/components/Pagination/index.vue
  31. 0 142
      src/components/PanThumb/index.vue
  32. 0 145
      src/components/RightPanel/index.vue
  33. 0 60
      src/components/Screenfull/index.vue
  34. 0 103
      src/components/Share/DropdownMenu.vue
  35. 0 57
      src/components/SizeSelect/index.vue
  36. 0 91
      src/components/Sticky/index.vue
  37. 0 1
      src/components/SvgIcon/index.vue
  38. 0 113
      src/components/TextHoverEffect/Mallki.vue
  39. 0 111
      src/components/Tinymce/components/EditorImage.vue
  40. 0 59
      src/components/Tinymce/dynamicLoadScript.js
  41. 0 247
      src/components/Tinymce/index.vue
  42. 0 7
      src/components/Tinymce/plugins.js
  43. 0 6
      src/components/Tinymce/toolbar.js
  44. 0 134
      src/components/Upload/SingleImage.vue
  45. 0 130
      src/components/Upload/SingleImage2.vue
  46. 0 157
      src/components/Upload/SingleImage3.vue
  47. 0 138
      src/components/UploadExcel/index.vue
  48. 1 2
      src/filters/index.js
  49. 0 1
      src/utils/request.js
  50. 20 20
      src/views/equipment-monitoring/components/SubTitle.vue
  51. 1 4
      src/views/error-page/404.vue
  52. 12 13
      src/views/permission/role.vue
  53. 9 1
      src/views/power-change-monitoring/index.vue
  54. 6 9
      vue.config.js

+ 0 - 8
.env.staging

@@ -1,8 +0,0 @@
-NODE_ENV = production
-
-# just a flag
-ENV = 'staging'
-
-# base api
-VUE_APP_BASE_API = '/stage-api'
-

+ 0 - 5
.travis.yml

@@ -1,5 +0,0 @@
-language: node_js
-node_js: 10
-script: npm run test
-notifications:
-  email: false

+ 0 - 21
LICENSE

@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2017-present PanJiaChen
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.

+ 0 - 24
jest.config.js

@@ -1,24 +0,0 @@
-module.exports = {
-  moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
-  transform: {
-    '^.+\\.vue$': 'vue-jest',
-    '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
-      'jest-transform-stub',
-    '^.+\\.jsx?$': 'babel-jest'
-  },
-  moduleNameMapper: {
-    '^@/(.*)$': '<rootDir>/src/$1'
-  },
-  snapshotSerializers: ['jest-serializer-vue'],
-  testMatch: [
-    '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
-  ],
-  collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'],
-  coverageDirectory: '<rootDir>/tests/unit/coverage',
-  // 'collectCoverage': true,
-  'coverageReporters': [
-    'lcov',
-    'text-summary'
-  ],
-  testURL: 'http://localhost/'
-}

+ 0 - 9
jsconfig.json

@@ -1,9 +0,0 @@
-{ 
-  "compilerOptions": {
-    "baseUrl": "./",
-    "paths": {
-        "@/*": ["src/*"]
-    }
-  },
-  "exclude": ["node_modules", "dist"]
-}

+ 0 - 9
plopfile.js

@@ -1,9 +0,0 @@
-const viewGenerator = require('./plop-templates/view/prompt')
-const componentGenerator = require('./plop-templates/component/prompt')
-const storeGenerator = require('./plop-templates/store/prompt.js')
-
-module.exports = function(plop) {
-  plop.setGenerator('view', viewGenerator)
-  plop.setGenerator('component', componentGenerator)
-  plop.setGenerator('store', storeGenerator)
-}

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

@@ -1,111 +0,0 @@
-<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"><path d="M12.036 15.59a1 1 0 0 1-.997.995H5.032a.996.996 0 0 1-.997-.996V8.584H1.03c-1.1 0-1.36-.633-.578-1.416L7.33.29a1.003 1.003 0 0 1 1.412 0l6.878 6.88c.782.78.523 1.415-.58 1.415h-3.004v7.004z" /></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>

+ 0 - 82
src/components/Breadcrumb/index.vue

@@ -1,82 +0,0 @@
-<template>
-  <el-breadcrumb class="app-breadcrumb" separator="/">
-    <transition-group name="breadcrumb">
-      <el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
-        <span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span>
-        <a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
-      </el-breadcrumb-item>
-    </transition-group>
-  </el-breadcrumb>
-</template>
-
-<script>
-import pathToRegexp from 'path-to-regexp'
-
-export default {
-  data() {
-    return {
-      levelList: null
-    }
-  },
-  watch: {
-    $route(route) {
-      // if you go to the redirect page, do not update the breadcrumbs
-      if (route.path.startsWith('/redirect/')) {
-        return
-      }
-      this.getBreadcrumb()
-    }
-  },
-  created() {
-    this.getBreadcrumb()
-  },
-  methods: {
-    getBreadcrumb() {
-      // only show routes with meta.title
-      let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
-      const first = matched[0]
-
-      if (!this.isDashboard(first)) {
-        matched = [{ path: '/dashboard', meta: { title: 'Dashboard' }}].concat(matched)
-      }
-
-      this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
-    },
-    isDashboard(route) {
-      const name = route && route.name
-      if (!name) {
-        return false
-      }
-      return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
-    },
-    pathCompile(path) {
-      // To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
-      const { params } = this.$route
-      var toPath = pathToRegexp.compile(path)
-      return toPath(params)
-    },
-    handleLink(item) {
-      const { redirect, path } = item
-      if (redirect) {
-        this.$router.push(redirect)
-        return
-      }
-      this.$router.push(this.pathCompile(path))
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.app-breadcrumb.el-breadcrumb {
-  display: inline-block;
-  font-size: 14px;
-  line-height: 50px;
-  margin-left: 8px;
-
-  .no-redirect {
-    color: #97a8be;
-    cursor: text;
-  }
-}
-</style>

+ 0 - 155
src/components/Charts/Keyboard.vue

@@ -1,155 +0,0 @@
-<template>
-  <div :id="id" :class="className" :style="{height:height,width:width}" />
-</template>
-
-<script>
-import echarts from 'echarts'
-import resize from './mixins/resize'
-
-export default {
-  mixins: [resize],
-  props: {
-    className: {
-      type: String,
-      default: 'chart'
-    },
-    id: {
-      type: String,
-      default: 'chart'
-    },
-    width: {
-      type: String,
-      default: '200px'
-    },
-    height: {
-      type: String,
-      default: '200px'
-    }
-  },
-  data() {
-    return {
-      chart: null
-    }
-  },
-  mounted() {
-    this.initChart()
-  },
-  beforeDestroy() {
-    if (!this.chart) {
-      return
-    }
-    this.chart.dispose()
-    this.chart = null
-  },
-  methods: {
-    initChart() {
-      this.chart = echarts.init(document.getElementById(this.id))
-
-      const xAxisData = []
-      const data = []
-      const data2 = []
-      for (let i = 0; i < 50; i++) {
-        xAxisData.push(i)
-        data.push((Math.sin(i / 5) * (i / 5 - 10) + i / 6) * 5)
-        data2.push((Math.sin(i / 5) * (i / 5 + 10) + i / 6) * 3)
-      }
-      this.chart.setOption({
-        backgroundColor: '#08263a',
-        grid: {
-          left: '5%',
-          right: '5%'
-        },
-        xAxis: [{
-          show: false,
-          data: xAxisData
-        }, {
-          show: false,
-          data: xAxisData
-        }],
-        visualMap: {
-          show: false,
-          min: 0,
-          max: 50,
-          dimension: 0,
-          inRange: {
-            color: ['#4a657a', '#308e92', '#b1cfa5', '#f5d69f', '#f5898b', '#ef5055']
-          }
-        },
-        yAxis: {
-          axisLine: {
-            show: false
-          },
-          axisLabel: {
-            textStyle: {
-              color: '#4a657a'
-            }
-          },
-          splitLine: {
-            show: true,
-            lineStyle: {
-              color: '#08263f'
-            }
-          },
-          axisTick: {
-            show: false
-          }
-        },
-        series: [{
-          name: 'back',
-          type: 'bar',
-          data: data2,
-          z: 1,
-          itemStyle: {
-            normal: {
-              opacity: 0.4,
-              barBorderRadius: 5,
-              shadowBlur: 3,
-              shadowColor: '#111'
-            }
-          }
-        }, {
-          name: 'Simulate Shadow',
-          type: 'line',
-          data,
-          z: 2,
-          showSymbol: false,
-          animationDelay: 0,
-          animationEasing: 'linear',
-          animationDuration: 1200,
-          lineStyle: {
-            normal: {
-              color: 'transparent'
-            }
-          },
-          areaStyle: {
-            normal: {
-              color: '#08263a',
-              shadowBlur: 50,
-              shadowColor: '#000'
-            }
-          }
-        }, {
-          name: 'front',
-          type: 'bar',
-          data,
-          xAxisIndex: 1,
-          z: 3,
-          itemStyle: {
-            normal: {
-              barBorderRadius: 5
-            }
-          }
-        }],
-        animationEasing: 'elasticOut',
-        animationEasingUpdate: 'elasticOut',
-        animationDelay(idx) {
-          return idx * 20
-        },
-        animationDelayUpdate(idx) {
-          return idx * 20
-        }
-      })
-    }
-  }
-}
-</script>

+ 0 - 227
src/components/Charts/LineMarker.vue

@@ -1,227 +0,0 @@
-<template>
-  <div :id="id" :class="className" :style="{height:height,width:width}" />
-</template>
-
-<script>
-import echarts from 'echarts'
-import resize from './mixins/resize'
-
-export default {
-  mixins: [resize],
-  props: {
-    className: {
-      type: String,
-      default: 'chart'
-    },
-    id: {
-      type: String,
-      default: 'chart'
-    },
-    width: {
-      type: String,
-      default: '200px'
-    },
-    height: {
-      type: String,
-      default: '200px'
-    }
-  },
-  data() {
-    return {
-      chart: null
-    }
-  },
-  mounted() {
-    this.initChart()
-  },
-  beforeDestroy() {
-    if (!this.chart) {
-      return
-    }
-    this.chart.dispose()
-    this.chart = null
-  },
-  methods: {
-    initChart() {
-      this.chart = echarts.init(document.getElementById(this.id))
-
-      this.chart.setOption({
-        backgroundColor: '#394056',
-        title: {
-          top: 20,
-          text: 'Requests',
-          textStyle: {
-            fontWeight: 'normal',
-            fontSize: 16,
-            color: '#F1F1F3'
-          },
-          left: '1%'
-        },
-        tooltip: {
-          trigger: 'axis',
-          axisPointer: {
-            lineStyle: {
-              color: '#57617B'
-            }
-          }
-        },
-        legend: {
-          top: 20,
-          icon: 'rect',
-          itemWidth: 14,
-          itemHeight: 5,
-          itemGap: 13,
-          data: ['CMCC', 'CTCC', 'CUCC'],
-          right: '4%',
-          textStyle: {
-            fontSize: 12,
-            color: '#F1F1F3'
-          }
-        },
-        grid: {
-          top: 100,
-          left: '2%',
-          right: '2%',
-          bottom: '2%',
-          containLabel: true
-        },
-        xAxis: [{
-          type: 'category',
-          boundaryGap: false,
-          axisLine: {
-            lineStyle: {
-              color: '#57617B'
-            }
-          },
-          data: ['13:00', '13:05', '13:10', '13:15', '13:20', '13:25', '13:30', '13:35', '13:40', '13:45', '13:50', '13:55']
-        }],
-        yAxis: [{
-          type: 'value',
-          name: '(%)',
-          axisTick: {
-            show: false
-          },
-          axisLine: {
-            lineStyle: {
-              color: '#57617B'
-            }
-          },
-          axisLabel: {
-            margin: 10,
-            textStyle: {
-              fontSize: 14
-            }
-          },
-          splitLine: {
-            lineStyle: {
-              color: '#57617B'
-            }
-          }
-        }],
-        series: [{
-          name: 'CMCC',
-          type: 'line',
-          smooth: true,
-          symbol: 'circle',
-          symbolSize: 5,
-          showSymbol: false,
-          lineStyle: {
-            normal: {
-              width: 1
-            }
-          },
-          areaStyle: {
-            normal: {
-              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
-                offset: 0,
-                color: 'rgba(137, 189, 27, 0.3)'
-              }, {
-                offset: 0.8,
-                color: 'rgba(137, 189, 27, 0)'
-              }], false),
-              shadowColor: 'rgba(0, 0, 0, 0.1)',
-              shadowBlur: 10
-            }
-          },
-          itemStyle: {
-            normal: {
-              color: 'rgb(137,189,27)',
-              borderColor: 'rgba(137,189,2,0.27)',
-              borderWidth: 12
-
-            }
-          },
-          data: [220, 182, 191, 134, 150, 120, 110, 125, 145, 122, 165, 122]
-        }, {
-          name: 'CTCC',
-          type: 'line',
-          smooth: true,
-          symbol: 'circle',
-          symbolSize: 5,
-          showSymbol: false,
-          lineStyle: {
-            normal: {
-              width: 1
-            }
-          },
-          areaStyle: {
-            normal: {
-              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
-                offset: 0,
-                color: 'rgba(0, 136, 212, 0.3)'
-              }, {
-                offset: 0.8,
-                color: 'rgba(0, 136, 212, 0)'
-              }], false),
-              shadowColor: 'rgba(0, 0, 0, 0.1)',
-              shadowBlur: 10
-            }
-          },
-          itemStyle: {
-            normal: {
-              color: 'rgb(0,136,212)',
-              borderColor: 'rgba(0,136,212,0.2)',
-              borderWidth: 12
-
-            }
-          },
-          data: [120, 110, 125, 145, 122, 165, 122, 220, 182, 191, 134, 150]
-        }, {
-          name: 'CUCC',
-          type: 'line',
-          smooth: true,
-          symbol: 'circle',
-          symbolSize: 5,
-          showSymbol: false,
-          lineStyle: {
-            normal: {
-              width: 1
-            }
-          },
-          areaStyle: {
-            normal: {
-              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
-                offset: 0,
-                color: 'rgba(219, 50, 51, 0.3)'
-              }, {
-                offset: 0.8,
-                color: 'rgba(219, 50, 51, 0)'
-              }], false),
-              shadowColor: 'rgba(0, 0, 0, 0.1)',
-              shadowBlur: 10
-            }
-          },
-          itemStyle: {
-            normal: {
-              color: 'rgb(219,50,51)',
-              borderColor: 'rgba(219,50,51,0.2)',
-              borderWidth: 12
-            }
-          },
-          data: [220, 182, 125, 145, 122, 191, 134, 150, 120, 110, 165, 122]
-        }]
-      })
-    }
-  }
-}
-</script>

+ 0 - 271
src/components/Charts/MixChart.vue

@@ -1,271 +0,0 @@
-<template>
-  <div :id="id" :class="className" :style="{height:height,width:width}" />
-</template>
-
-<script>
-import echarts from 'echarts'
-import resize from './mixins/resize'
-
-export default {
-  mixins: [resize],
-  props: {
-    className: {
-      type: String,
-      default: 'chart'
-    },
-    id: {
-      type: String,
-      default: 'chart'
-    },
-    width: {
-      type: String,
-      default: '200px'
-    },
-    height: {
-      type: String,
-      default: '200px'
-    }
-  },
-  data() {
-    return {
-      chart: null
-    }
-  },
-  mounted() {
-    this.initChart()
-  },
-  beforeDestroy() {
-    if (!this.chart) {
-      return
-    }
-    this.chart.dispose()
-    this.chart = null
-  },
-  methods: {
-    initChart() {
-      this.chart = echarts.init(document.getElementById(this.id))
-      const xData = (function() {
-        const data = []
-        for (let i = 1; i < 13; i++) {
-          data.push(i + 'month')
-        }
-        return data
-      }())
-      this.chart.setOption({
-        backgroundColor: '#344b58',
-        title: {
-          text: 'statistics',
-          x: '20',
-          top: '20',
-          textStyle: {
-            color: '#fff',
-            fontSize: '22'
-          },
-          subtextStyle: {
-            color: '#90979c',
-            fontSize: '16'
-          }
-        },
-        tooltip: {
-          trigger: 'axis',
-          axisPointer: {
-            textStyle: {
-              color: '#fff'
-            }
-          }
-        },
-        grid: {
-          left: '5%',
-          right: '5%',
-          borderWidth: 0,
-          top: 150,
-          bottom: 95,
-          textStyle: {
-            color: '#fff'
-          }
-        },
-        legend: {
-          x: '5%',
-          top: '10%',
-          textStyle: {
-            color: '#90979c'
-          },
-          data: ['female', 'male', 'average']
-        },
-        calculable: true,
-        xAxis: [{
-          type: 'category',
-          axisLine: {
-            lineStyle: {
-              color: '#90979c'
-            }
-          },
-          splitLine: {
-            show: false
-          },
-          axisTick: {
-            show: false
-          },
-          splitArea: {
-            show: false
-          },
-          axisLabel: {
-            interval: 0
-
-          },
-          data: xData
-        }],
-        yAxis: [{
-          type: 'value',
-          splitLine: {
-            show: false
-          },
-          axisLine: {
-            lineStyle: {
-              color: '#90979c'
-            }
-          },
-          axisTick: {
-            show: false
-          },
-          axisLabel: {
-            interval: 0
-          },
-          splitArea: {
-            show: false
-          }
-        }],
-        dataZoom: [{
-          show: true,
-          height: 30,
-          xAxisIndex: [
-            0
-          ],
-          bottom: 30,
-          start: 10,
-          end: 80,
-          handleIcon: 'path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z',
-          handleSize: '110%',
-          handleStyle: {
-            color: '#d3dee5'
-
-          },
-          textStyle: {
-            color: '#fff' },
-          borderColor: '#90979c'
-
-        }, {
-          type: 'inside',
-          show: true,
-          height: 15,
-          start: 1,
-          end: 35
-        }],
-        series: [{
-          name: 'female',
-          type: 'bar',
-          stack: 'total',
-          barMaxWidth: 35,
-          barGap: '10%',
-          itemStyle: {
-            normal: {
-              color: 'rgba(255,144,128,1)',
-              label: {
-                show: true,
-                textStyle: {
-                  color: '#fff'
-                },
-                position: 'insideTop',
-                formatter(p) {
-                  return p.value > 0 ? p.value : ''
-                }
-              }
-            }
-          },
-          data: [
-            709,
-            1917,
-            2455,
-            2610,
-            1719,
-            1433,
-            1544,
-            3285,
-            5208,
-            3372,
-            2484,
-            4078
-          ]
-        },
-
-        {
-          name: 'male',
-          type: 'bar',
-          stack: 'total',
-          itemStyle: {
-            normal: {
-              color: 'rgba(0,191,183,1)',
-              barBorderRadius: 0,
-              label: {
-                show: true,
-                position: 'top',
-                formatter(p) {
-                  return p.value > 0 ? p.value : ''
-                }
-              }
-            }
-          },
-          data: [
-            327,
-            1776,
-            507,
-            1200,
-            800,
-            482,
-            204,
-            1390,
-            1001,
-            951,
-            381,
-            220
-          ]
-        }, {
-          name: 'average',
-          type: 'line',
-          stack: 'total',
-          symbolSize: 10,
-          symbol: 'circle',
-          itemStyle: {
-            normal: {
-              color: 'rgba(252,230,48,1)',
-              barBorderRadius: 0,
-              label: {
-                show: true,
-                position: 'top',
-                formatter(p) {
-                  return p.value > 0 ? p.value : ''
-                }
-              }
-            }
-          },
-          data: [
-            1036,
-            3693,
-            2962,
-            3810,
-            2519,
-            1915,
-            1748,
-            4675,
-            6209,
-            4323,
-            2865,
-            4298
-          ]
-        }
-        ]
-      })
-    }
-  }
-}
-</script>

+ 0 - 56
src/components/Charts/mixins/resize.js

@@ -1,56 +0,0 @@
-import { debounce } from '@/utils'
-
-export default {
-  data() {
-    return {
-      $_sidebarElm: null,
-      $_resizeHandler: null
-    }
-  },
-  mounted() {
-    this.initListener()
-  },
-  activated() {
-    if (!this.$_resizeHandler) {
-      // avoid duplication init
-      this.initListener()
-    }
-
-    // when keep-alive chart activated, auto resize
-    this.resize()
-  },
-  beforeDestroy() {
-    this.destroyListener()
-  },
-  deactivated() {
-    this.destroyListener()
-  },
-  methods: {
-    // use $_ for mixins properties
-    // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
-    $_sidebarResizeHandler(e) {
-      if (e.propertyName === 'width') {
-        this.$_resizeHandler()
-      }
-    },
-    initListener() {
-      this.$_resizeHandler = debounce(() => {
-        this.resize()
-      }, 100)
-      window.addEventListener('resize', this.$_resizeHandler)
-
-      this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
-      this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
-    },
-    destroyListener() {
-      window.removeEventListener('resize', this.$_resizeHandler)
-      this.$_resizeHandler = null
-
-      this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
-    },
-    resize() {
-      const { chart } = this
-      chart && chart.resize()
-    }
-  }
-}

+ 0 - 166
src/components/DndList/index.vue

@@ -1,166 +0,0 @@
-<template>
-  <div class="dndList">
-    <div :style="{width:width1}" class="dndList-list">
-      <h3>{{ list1Title }}</h3>
-      <draggable :set-data="setData" :list="list1" group="article" class="dragArea">
-        <div v-for="element in list1" :key="element.id" class="list-complete-item">
-          <div class="list-complete-item-handle">
-            {{ element.id }}[{{ element.author }}] {{ element.title }}
-          </div>
-          <div style="position:absolute;right:0px;">
-            <span style="float: right ;margin-top: -20px;margin-right:5px;" @click="deleteEle(element)">
-              <i style="color:#ff4949" class="el-icon-delete" />
-            </span>
-          </div>
-        </div>
-      </draggable>
-    </div>
-    <div :style="{width:width2}" class="dndList-list">
-      <h3>{{ list2Title }}</h3>
-      <draggable :list="list2" group="article" class="dragArea">
-        <div v-for="element in list2" :key="element.id" class="list-complete-item">
-          <div class="list-complete-item-handle2" @click="pushEle(element)">
-            {{ element.id }} [{{ element.author }}] {{ element.title }}
-          </div>
-        </div>
-      </draggable>
-    </div>
-  </div>
-</template>
-
-<script>
-import draggable from 'vuedraggable'
-
-export default {
-  name: 'DndList',
-  components: { draggable },
-  props: {
-    list1: {
-      type: Array,
-      default() {
-        return []
-      }
-    },
-    list2: {
-      type: Array,
-      default() {
-        return []
-      }
-    },
-    list1Title: {
-      type: String,
-      default: 'list1'
-    },
-    list2Title: {
-      type: String,
-      default: 'list2'
-    },
-    width1: {
-      type: String,
-      default: '48%'
-    },
-    width2: {
-      type: String,
-      default: '48%'
-    }
-  },
-  methods: {
-    isNotInList1(v) {
-      return this.list1.every(k => v.id !== k.id)
-    },
-    isNotInList2(v) {
-      return this.list2.every(k => v.id !== k.id)
-    },
-    deleteEle(ele) {
-      for (const item of this.list1) {
-        if (item.id === ele.id) {
-          const index = this.list1.indexOf(item)
-          this.list1.splice(index, 1)
-          break
-        }
-      }
-      if (this.isNotInList2(ele)) {
-        this.list2.unshift(ele)
-      }
-    },
-    pushEle(ele) {
-      for (const item of this.list2) {
-        if (item.id === ele.id) {
-          const index = this.list2.indexOf(item)
-          this.list2.splice(index, 1)
-          break
-        }
-      }
-      if (this.isNotInList1(ele)) {
-        this.list1.push(ele)
-      }
-    },
-    setData(dataTransfer) {
-      // to avoid Firefox bug
-      // Detail see : https://github.com/RubaXa/Sortable/issues/1012
-      dataTransfer.setData('Text', '')
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.dndList {
-  background: #fff;
-  padding-bottom: 40px;
-  &:after {
-    content: "";
-    display: table;
-    clear: both;
-  }
-  .dndList-list {
-    float: left;
-    padding-bottom: 30px;
-    &:first-of-type {
-      margin-right: 2%;
-    }
-    .dragArea {
-      margin-top: 15px;
-      min-height: 50px;
-      padding-bottom: 30px;
-    }
-  }
-}
-
-.list-complete-item {
-  cursor: pointer;
-  position: relative;
-  font-size: 14px;
-  padding: 5px 12px;
-  margin-top: 4px;
-  border: 1px solid #bfcbd9;
-  transition: all 1s;
-}
-
-.list-complete-item-handle {
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  margin-right: 50px;
-}
-
-.list-complete-item-handle2 {
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  margin-right: 20px;
-}
-
-.list-complete-item.sortable-chosen {
-  background: #4AB7BD;
-}
-
-.list-complete-item.sortable-ghost {
-  background: #30B08F;
-}
-
-.list-complete-enter,
-.list-complete-leave-active {
-  opacity: 0;
-}
-</style>

+ 0 - 65
src/components/DragSelect/index.vue

@@ -1,65 +0,0 @@
-<template>
-  <el-select ref="dragSelect" v-model="selectVal" v-bind="$attrs" class="drag-select" multiple v-on="$listeners">
-    <slot />
-  </el-select>
-</template>
-
-<script>
-import Sortable from 'sortablejs'
-
-export default {
-  name: 'DragSelect',
-  props: {
-    value: {
-      type: Array,
-      required: true
-    }
-  },
-  computed: {
-    selectVal: {
-      get() {
-        return [...this.value]
-      },
-      set(val) {
-        this.$emit('input', [...val])
-      }
-    }
-  },
-  mounted() {
-    this.setSort()
-  },
-  methods: {
-    setSort() {
-      const el = this.$refs.dragSelect.$el.querySelectorAll('.el-select__tags > span')[0]
-      this.sortable = Sortable.create(el, {
-        ghostClass: 'sortable-ghost', // Class name for the drop placeholder,
-        setData: function(dataTransfer) {
-          dataTransfer.setData('Text', '')
-          // to avoid Firefox bug
-          // Detail see : https://github.com/RubaXa/Sortable/issues/1012
-        },
-        onEnd: evt => {
-          const targetRow = this.value.splice(evt.oldIndex, 1)[0]
-          this.value.splice(evt.newIndex, 0, targetRow)
-        }
-      })
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.drag-select {
-  ::v-deep {
-    .sortable-ghost {
-      opacity: .8;
-      color: #fff !important;
-      background: #42b983 !important;
-    }
-
-    .el-tag {
-      cursor: pointer;
-    }
-  }
-}
-</style>

+ 0 - 297
src/components/Dropzone/index.vue

@@ -1,297 +0,0 @@
-<template>
-  <div :id="id" :ref="id" :action="url" class="dropzone">
-    <input type="file" name="file">
-  </div>
-</template>
-
-<script>
-import Dropzone from 'dropzone'
-import 'dropzone/dist/dropzone.css'
-// import { getToken } from 'api/qiniu';
-
-Dropzone.autoDiscover = false
-
-export default {
-  props: {
-    id: {
-      type: String,
-      required: true
-    },
-    url: {
-      type: String,
-      required: true
-    },
-    clickable: {
-      type: Boolean,
-      default: true
-    },
-    defaultMsg: {
-      type: String,
-      default: '上传图片'
-    },
-    acceptedFiles: {
-      type: String,
-      default: ''
-    },
-    thumbnailHeight: {
-      type: Number,
-      default: 200
-    },
-    thumbnailWidth: {
-      type: Number,
-      default: 200
-    },
-    showRemoveLink: {
-      type: Boolean,
-      default: true
-    },
-    maxFilesize: {
-      type: Number,
-      default: 2
-    },
-    maxFiles: {
-      type: Number,
-      default: 3
-    },
-    autoProcessQueue: {
-      type: Boolean,
-      default: true
-    },
-    useCustomDropzoneOptions: {
-      type: Boolean,
-      default: false
-    },
-    defaultImg: {
-      default: '',
-      type: [String, Array]
-    },
-    couldPaste: {
-      type: Boolean,
-      default: false
-    }
-  },
-  data() {
-    return {
-      dropzone: '',
-      initOnce: true
-    }
-  },
-  watch: {
-    defaultImg(val) {
-      if (val.length === 0) {
-        this.initOnce = false
-        return
-      }
-      if (!this.initOnce) return
-      this.initImages(val)
-      this.initOnce = false
-    }
-  },
-  mounted() {
-    const element = document.getElementById(this.id)
-    const vm = this
-    this.dropzone = new Dropzone(element, {
-      clickable: this.clickable,
-      thumbnailWidth: this.thumbnailWidth,
-      thumbnailHeight: this.thumbnailHeight,
-      maxFiles: this.maxFiles,
-      maxFilesize: this.maxFilesize,
-      dictRemoveFile: 'Remove',
-      addRemoveLinks: this.showRemoveLink,
-      acceptedFiles: this.acceptedFiles,
-      autoProcessQueue: this.autoProcessQueue,
-      dictDefaultMessage: '<i style="margin-top: 3em;display: inline-block" class="material-icons">' + this.defaultMsg + '</i><br>Drop files here to upload',
-      dictMaxFilesExceeded: '只能一个图',
-      previewTemplate: '<div class="dz-preview dz-file-preview">  <div class="dz-image" style="width:' + this.thumbnailWidth + 'px;height:' + this.thumbnailHeight + 'px" ><img style="width:' + this.thumbnailWidth + 'px;height:' + this.thumbnailHeight + 'px" data-dz-thumbnail /></div>  <div class="dz-details"><div class="dz-size"><span data-dz-size></span></div> <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>  <div class="dz-error-message"><span data-dz-errormessage></span></div>  <div class="dz-success-mark"> <i class="material-icons">done</i> </div>  <div class="dz-error-mark"><i class="material-icons">error</i></div></div>',
-      init() {
-        const val = vm.defaultImg
-        if (!val) return
-        if (Array.isArray(val)) {
-          if (val.length === 0) return
-          val.map((v, i) => {
-            const mockFile = { name: 'name' + i, size: 12345, url: v }
-            this.options.addedfile.call(this, mockFile)
-            this.options.thumbnail.call(this, mockFile, v)
-            mockFile.previewElement.classList.add('dz-success')
-            mockFile.previewElement.classList.add('dz-complete')
-            vm.initOnce = false
-            return true
-          })
-        } else {
-          const mockFile = { name: 'name', size: 12345, url: val }
-          this.options.addedfile.call(this, mockFile)
-          this.options.thumbnail.call(this, mockFile, val)
-          mockFile.previewElement.classList.add('dz-success')
-          mockFile.previewElement.classList.add('dz-complete')
-          vm.initOnce = false
-        }
-      },
-      accept: (file, done) => {
-        /* 七牛*/
-        // const token = this.$store.getters.token;
-        // getToken(token).then(response => {
-        //   file.token = response.data.qiniu_token;
-        //   file.key = response.data.qiniu_key;
-        //   file.url = response.data.qiniu_url;
-        //   done();
-        // })
-        done()
-      },
-      sending: (file, xhr, formData) => {
-        // formData.append('token', file.token);
-        // formData.append('key', file.key);
-        vm.initOnce = false
-      }
-    })
-
-    if (this.couldPaste) {
-      document.addEventListener('paste', this.pasteImg)
-    }
-
-    this.dropzone.on('success', file => {
-      vm.$emit('dropzone-success', file, vm.dropzone.element)
-    })
-    this.dropzone.on('addedfile', file => {
-      vm.$emit('dropzone-fileAdded', file)
-    })
-    this.dropzone.on('removedfile', file => {
-      vm.$emit('dropzone-removedFile', file)
-    })
-    this.dropzone.on('error', (file, error, xhr) => {
-      vm.$emit('dropzone-error', file, error, xhr)
-    })
-    this.dropzone.on('successmultiple', (file, error, xhr) => {
-      vm.$emit('dropzone-successmultiple', file, error, xhr)
-    })
-  },
-  destroyed() {
-    document.removeEventListener('paste', this.pasteImg)
-    this.dropzone.destroy()
-  },
-  methods: {
-    removeAllFiles() {
-      this.dropzone.removeAllFiles(true)
-    },
-    processQueue() {
-      this.dropzone.processQueue()
-    },
-    pasteImg(event) {
-      const items = (event.clipboardData || event.originalEvent.clipboardData).items
-      if (items[0].kind === 'file') {
-        this.dropzone.addFile(items[0].getAsFile())
-      }
-    },
-    initImages(val) {
-      if (!val) return
-      if (Array.isArray(val)) {
-        val.map((v, i) => {
-          const mockFile = { name: 'name' + i, size: 12345, url: v }
-          this.dropzone.options.addedfile.call(this.dropzone, mockFile)
-          this.dropzone.options.thumbnail.call(this.dropzone, mockFile, v)
-          mockFile.previewElement.classList.add('dz-success')
-          mockFile.previewElement.classList.add('dz-complete')
-          return true
-        })
-      } else {
-        const mockFile = { name: 'name', size: 12345, url: val }
-        this.dropzone.options.addedfile.call(this.dropzone, mockFile)
-        this.dropzone.options.thumbnail.call(this.dropzone, mockFile, val)
-        mockFile.previewElement.classList.add('dz-success')
-        mockFile.previewElement.classList.add('dz-complete')
-      }
-    }
-
-  }
-}
-</script>
-
-<style scoped>
-    .dropzone {
-        border: 2px solid #E5E5E5;
-        font-family: 'Roboto', sans-serif;
-        color: #777;
-        transition: background-color .2s linear;
-        padding: 5px;
-    }
-
-    .dropzone:hover {
-        background-color: #F6F6F6;
-    }
-
-    i {
-        color: #CCC;
-    }
-
-    .dropzone .dz-image img {
-        width: 100%;
-        height: 100%;
-    }
-
-    .dropzone input[name='file'] {
-        display: none;
-    }
-
-    .dropzone .dz-preview .dz-image {
-        border-radius: 0px;
-    }
-
-    .dropzone .dz-preview:hover .dz-image img {
-        transform: none;
-        filter: none;
-        width: 100%;
-        height: 100%;
-    }
-
-    .dropzone .dz-preview .dz-details {
-        bottom: 0px;
-        top: 0px;
-        color: white;
-        background-color: rgba(33, 150, 243, 0.8);
-        transition: opacity .2s linear;
-        text-align: left;
-    }
-
-    .dropzone .dz-preview .dz-details .dz-filename span, .dropzone .dz-preview .dz-details .dz-size span {
-        background-color: transparent;
-    }
-
-    .dropzone .dz-preview .dz-details .dz-filename:not(:hover) span {
-        border: none;
-    }
-
-    .dropzone .dz-preview .dz-details .dz-filename:hover span {
-        background-color: transparent;
-        border: none;
-    }
-
-    .dropzone .dz-preview .dz-remove {
-        position: absolute;
-        z-index: 30;
-        color: white;
-        margin-left: 15px;
-        padding: 10px;
-        top: inherit;
-        bottom: 15px;
-        border: 2px white solid;
-        text-decoration: none;
-        text-transform: uppercase;
-        font-size: 0.8rem;
-        font-weight: 800;
-        letter-spacing: 1.1px;
-        opacity: 0;
-    }
-
-    .dropzone .dz-preview:hover .dz-remove {
-        opacity: 1;
-    }
-
-    .dropzone .dz-preview .dz-success-mark, .dropzone .dz-preview .dz-error-mark {
-        margin-left: -40px;
-        margin-top: -50px;
-    }
-
-    .dropzone .dz-preview .dz-success-mark i, .dropzone .dz-preview .dz-error-mark i {
-        color: white;
-        font-size: 5rem;
-    }
-</style>

+ 0 - 78
src/components/ErrorLog/index.vue

@@ -1,78 +0,0 @@
-<template>
-  <div v-if="errorLogs.length>0">
-    <el-badge :is-dot="true" style="line-height: 25px;margin-top: -5px;" @click.native="dialogTableVisible=true">
-      <el-button style="padding: 8px 10px;" size="small" type="danger">
-        <svg-icon icon-class="bug" />
-      </el-button>
-    </el-badge>
-
-    <el-dialog :visible.sync="dialogTableVisible" width="80%" append-to-body>
-      <div slot="title">
-        <span style="padding-right: 10px;">Error Log</span>
-        <el-button size="mini" type="primary" icon="el-icon-delete" @click="clearAll">Clear All</el-button>
-      </div>
-      <el-table :data="errorLogs" border>
-        <el-table-column label="Message">
-          <template slot-scope="{row}">
-            <div>
-              <span class="message-title">Msg:</span>
-              <el-tag type="danger">
-                {{ row.err.message }}
-              </el-tag>
-            </div>
-            <br>
-            <div>
-              <span class="message-title" style="padding-right: 10px;">Info: </span>
-              <el-tag type="warning">
-                {{ row.vm.$vnode.tag }} error in {{ row.info }}
-              </el-tag>
-            </div>
-            <br>
-            <div>
-              <span class="message-title" style="padding-right: 16px;">Url: </span>
-              <el-tag type="success">
-                {{ row.url }}
-              </el-tag>
-            </div>
-          </template>
-        </el-table-column>
-        <el-table-column label="Stack">
-          <template slot-scope="scope">
-            {{ scope.row.err.stack }}
-          </template>
-        </el-table-column>
-      </el-table>
-    </el-dialog>
-  </div>
-</template>
-
-<script>
-export default {
-  name: 'ErrorLog',
-  data() {
-    return {
-      dialogTableVisible: false
-    }
-  },
-  computed: {
-    errorLogs() {
-      return this.$store.getters.errorLogs
-    }
-  },
-  methods: {
-    clearAll() {
-      this.dialogTableVisible = false
-      this.$store.dispatch('errorLog/clearErrorLog')
-    }
-  }
-}
-</script>
-
-<style scoped>
-.message-title {
-  font-size: 16px;
-  color: #333;
-  font-weight: bold;
-  padding-right: 8px;
-}
-</style>

+ 0 - 54
src/components/GithubCorner/index.vue

@@ -1,54 +0,0 @@
-<template>
-  <a href="https://github.com/PanJiaChen/vue-element-admin" target="_blank" class="github-corner" aria-label="View source on Github">
-    <svg
-      width="80"
-      height="80"
-      viewBox="0 0 250 250"
-      style="fill:#40c9c6; color:#fff;"
-      aria-hidden="true"
-    >
-      <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z" />
-      <path
-        d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
-        fill="currentColor"
-        style="transform-origin: 130px 106px;"
-        class="octo-arm"
-      />
-      <path
-        d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
-        fill="currentColor"
-        class="octo-body"
-      />
-    </svg>
-  </a>
-</template>
-
-<style scoped>
-.github-corner:hover .octo-arm {
-  animation: octocat-wave 560ms ease-in-out
-}
-
-@keyframes octocat-wave {
-  0%,
-  100% {
-    transform: rotate(0)
-  }
-  20%,
-  60% {
-    transform: rotate(-25deg)
-  }
-  40%,
-  80% {
-    transform: rotate(10deg)
-  }
-}
-
-@media (max-width:500px) {
-  .github-corner:hover .octo-arm {
-    animation: none
-  }
-  .github-corner .octo-arm {
-    animation: octocat-wave 560ms ease-in-out
-  }
-}
-</style>

+ 0 - 44
src/components/Hamburger/index.vue

@@ -1,44 +0,0 @@
-<template>
-  <div style="padding: 0 15px;" @click="toggleClick">
-    <svg
-      :class="{'is-active':isActive}"
-      class="hamburger"
-      viewBox="0 0 1024 1024"
-      xmlns="http://www.w3.org/2000/svg"
-      width="64"
-      height="64"
-    >
-      <path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" />
-    </svg>
-  </div>
-</template>
-
-<script>
-export default {
-  name: 'Hamburger',
-  props: {
-    isActive: {
-      type: Boolean,
-      default: false
-    }
-  },
-  methods: {
-    toggleClick() {
-      this.$emit('toggleClick')
-    }
-  }
-}
-</script>
-
-<style scoped>
-.hamburger {
-  display: inline-block;
-  vertical-align: middle;
-  width: 20px;
-  height: 20px;
-}
-
-.hamburger.is-active {
-  transform: rotate(180deg);
-}
-</style>

+ 0 - 180
src/components/HeaderSearch/index.vue

@@ -1,180 +0,0 @@
-<template>
-  <div :class="{'show':show}" class="header-search">
-    <svg-icon class-name="search-icon" icon-class="search" @click.stop="click" />
-    <el-select
-      ref="headerSearchSelect"
-      v-model="search"
-      :remote-method="querySearch"
-      filterable
-      default-first-option
-      remote
-      placeholder="Search"
-      class="header-search-select"
-      @change="change"
-    >
-      <el-option v-for="item in options" :key="item.path" :value="item" :label="item.title.join(' > ')" />
-    </el-select>
-  </div>
-</template>
-
-<script>
-// fuse is a lightweight fuzzy-search module
-// make search results more in line with expectations
-import Fuse from 'fuse.js'
-import path from 'path'
-
-export default {
-  name: 'HeaderSearch',
-  data() {
-    return {
-      search: '',
-      options: [],
-      searchPool: [],
-      show: false,
-      fuse: undefined
-    }
-  },
-  computed: {
-    routes() {
-      return this.$store.getters.permission_routes
-    }
-  },
-  watch: {
-    routes() {
-      this.searchPool = this.generateRoutes(this.routes)
-    },
-    searchPool(list) {
-      this.initFuse(list)
-    },
-    show(value) {
-      if (value) {
-        document.body.addEventListener('click', this.close)
-      } else {
-        document.body.removeEventListener('click', this.close)
-      }
-    }
-  },
-  mounted() {
-    this.searchPool = this.generateRoutes(this.routes)
-  },
-  methods: {
-    click() {
-      this.show = !this.show
-      if (this.show) {
-        this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus()
-      }
-    },
-    close() {
-      this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur()
-      this.options = []
-      this.show = false
-    },
-    change(val) {
-      this.$router.push(val.path)
-      this.search = ''
-      this.options = []
-      this.$nextTick(() => {
-        this.show = false
-      })
-    },
-    initFuse(list) {
-      this.fuse = new Fuse(list, {
-        shouldSort: true,
-        threshold: 0.4,
-        location: 0,
-        distance: 100,
-        maxPatternLength: 32,
-        minMatchCharLength: 1,
-        keys: [{
-          name: 'title',
-          weight: 0.7
-        }, {
-          name: 'path',
-          weight: 0.3
-        }]
-      })
-    },
-    // Filter out the routes that can be displayed in the sidebar
-    // And generate the internationalized title
-    generateRoutes(routes, basePath = '/', prefixTitle = []) {
-      let res = []
-
-      for (const router of routes) {
-        // skip hidden router
-        if (router.hidden) { continue }
-
-        const data = {
-          path: path.resolve(basePath, router.path),
-          title: [...prefixTitle]
-        }
-
-        if (router.meta && router.meta.title) {
-          data.title = [...data.title, router.meta.title]
-
-          if (router.redirect !== 'noRedirect') {
-            // only push the routes with title
-            // special case: need to exclude parent router without redirect
-            res.push(data)
-          }
-        }
-
-        // recursive child routes
-        if (router.children) {
-          const tempRoutes = this.generateRoutes(router.children, data.path, data.title)
-          if (tempRoutes.length >= 1) {
-            res = [...res, ...tempRoutes]
-          }
-        }
-      }
-      return res
-    },
-    querySearch(query) {
-      if (query !== '') {
-        this.options = this.fuse.search(query)
-      } else {
-        this.options = []
-      }
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.header-search {
-  font-size: 0 !important;
-
-  .search-icon {
-    cursor: pointer;
-    font-size: 18px;
-    vertical-align: middle;
-  }
-
-  .header-search-select {
-    font-size: 18px;
-    transition: width 0.2s;
-    width: 0;
-    overflow: hidden;
-    background: transparent;
-    border-radius: 0;
-    display: inline-block;
-    vertical-align: middle;
-
-    ::v-deep .el-input__inner {
-      border-radius: 0;
-      border: 0;
-      padding-left: 0;
-      padding-right: 0;
-      box-shadow: none !important;
-      border-bottom: 1px solid #d9d9d9;
-      vertical-align: middle;
-    }
-  }
-
-  &.show {
-    .header-search-select {
-      width: 210px;
-      margin-left: 10px;
-    }
-  }
-}
-</style>

+ 0 - 1779
src/components/ImageCropper/index.vue

@@ -1,1779 +0,0 @@
-<template>
-  <div v-show="value" class="vue-image-crop-upload">
-    <div class="vicp-wrap">
-      <div class="vicp-close" @click="off">
-        <i class="vicp-icon4" />
-      </div>
-
-      <div v-show="step == 1" class="vicp-step1">
-        <div
-          class="vicp-drop-area"
-          @dragleave="preventDefault"
-          @dragover="preventDefault"
-          @dragenter="preventDefault"
-          @click="handleClick"
-          @drop="handleChange"
-        >
-          <i v-show="loading != 1" class="vicp-icon1">
-            <i class="vicp-icon1-arrow" />
-            <i class="vicp-icon1-body" />
-            <i class="vicp-icon1-bottom" />
-          </i>
-          <span v-show="loading !== 1" class="vicp-hint">{{ lang.hint }}</span>
-          <span v-show="!isSupported" class="vicp-no-supported-hint">{{ lang.noSupported }}</span>
-          <input v-show="false" v-if="step == 1" ref="fileinput" type="file" @change="handleChange">
-        </div>
-        <div v-show="hasError" class="vicp-error">
-          <i class="vicp-icon2" />
-          {{ errorMsg }}
-        </div>
-        <div class="vicp-operate">
-          <a @click="off" @mousedown="ripple">{{ lang.btn.off }}</a>
-        </div>
-      </div>
-
-      <div v-if="step == 2" class="vicp-step2">
-        <div class="vicp-crop">
-          <div v-show="true" class="vicp-crop-left">
-            <div class="vicp-img-container">
-              <img
-                ref="img"
-                :src="sourceImgUrl"
-                :style="sourceImgStyle"
-                class="vicp-img"
-                draggable="false"
-                @drag="preventDefault"
-                @dragstart="preventDefault"
-                @dragend="preventDefault"
-                @dragleave="preventDefault"
-                @dragover="preventDefault"
-                @dragenter="preventDefault"
-                @drop="preventDefault"
-                @touchstart="imgStartMove"
-                @touchmove="imgMove"
-                @touchend="createImg"
-                @touchcancel="createImg"
-                @mousedown="imgStartMove"
-                @mousemove="imgMove"
-                @mouseup="createImg"
-                @mouseout="createImg"
-              >
-              <div :style="sourceImgShadeStyle" class="vicp-img-shade vicp-img-shade-1" />
-              <div :style="sourceImgShadeStyle" class="vicp-img-shade vicp-img-shade-2" />
-            </div>
-
-            <div class="vicp-range">
-              <input
-                :value="scale.range"
-                type="range"
-                step="1"
-                min="0"
-                max="100"
-                @input="zoomChange"
-              >
-              <i
-                class="vicp-icon5"
-                @mousedown="startZoomSub"
-                @mouseout="endZoomSub"
-                @mouseup="endZoomSub"
-              />
-              <i
-                class="vicp-icon6"
-                @mousedown="startZoomAdd"
-                @mouseout="endZoomAdd"
-                @mouseup="endZoomAdd"
-              />
-            </div>
-
-            <div v-if="!noRotate" class="vicp-rotate">
-              <i @mousedown="startRotateLeft" @mouseout="endRotate" @mouseup="endRotate">↺</i>
-              <i @mousedown="startRotateRight" @mouseout="endRotate" @mouseup="endRotate">↻</i>
-            </div>
-          </div>
-          <div v-show="true" class="vicp-crop-right">
-            <div class="vicp-preview">
-              <div v-if="!noSquare" class="vicp-preview-item">
-                <img :src="createImgUrl" :style="previewStyle">
-                <span>{{ lang.preview }}</span>
-              </div>
-              <div v-if="!noCircle" class="vicp-preview-item vicp-preview-item-circle">
-                <img :src="createImgUrl" :style="previewStyle">
-                <span>{{ lang.preview }}</span>
-              </div>
-            </div>
-          </div>
-        </div>
-        <div class="vicp-operate">
-          <a @click="setStep(1)" @mousedown="ripple">{{ lang.btn.back }}</a>
-          <a class="vicp-operate-btn" @click="prepareUpload" @mousedown="ripple">{{ lang.btn.save }}</a>
-        </div>
-      </div>
-
-      <div v-if="step == 3" class="vicp-step3">
-        <div class="vicp-upload">
-          <span v-show="loading === 1" class="vicp-loading">{{ lang.loading }}</span>
-          <div class="vicp-progress-wrap">
-            <span v-show="loading === 1" :style="progressStyle" class="vicp-progress" />
-          </div>
-          <div v-show="hasError" class="vicp-error">
-            <i class="vicp-icon2" />
-            {{ errorMsg }}
-          </div>
-          <div v-show="loading === 2" class="vicp-success">
-            <i class="vicp-icon3" />
-            {{ lang.success }}
-          </div>
-        </div>
-        <div class="vicp-operate">
-          <a @click="setStep(2)" @mousedown="ripple">{{ lang.btn.back }}</a>
-          <a @click="off" @mousedown="ripple">{{ lang.btn.close }}</a>
-        </div>
-      </div>
-      <canvas v-show="false" ref="canvas" :width="width" :height="height" />
-    </div>
-  </div>
-</template>
-
-<script>
-'use strict'
-import request from '@/utils/request'
-import language from './utils/language.js'
-import mimes from './utils/mimes.js'
-import data2blob from './utils/data2blob.js'
-import effectRipple from './utils/effectRipple.js'
-export default {
-  props: {
-    // 域,上传文件name,触发事件会带上(如果一个页面多个图片上传控件,可以做区分
-    field: {
-      type: String,
-      default: 'avatar'
-    },
-    // 原名key,类似于id,触发事件会带上(如果一个页面多个图片上传控件,可以做区分
-    ki: {
-      type: Number,
-      default: 0
-    },
-    // 显示该控件与否
-    value: {
-      type: Boolean,
-      default: true
-    },
-    // 上传地址
-    url: {
-      type: String,
-      default: ''
-    },
-    // 其他要上传文件附带的数据,对象格式
-    params: {
-      type: Object,
-      default: null
-    },
-    // Add custom headers
-    headers: {
-      type: Object,
-      default: null
-    },
-    // 剪裁图片的宽
-    width: {
-      type: Number,
-      default: 200
-    },
-    // 剪裁图片的高
-    height: {
-      type: Number,
-      default: 200
-    },
-    // 不显示旋转功能
-    noRotate: {
-      type: Boolean,
-      default: true
-    },
-    // 不预览圆形图片
-    noCircle: {
-      type: Boolean,
-      default: false
-    },
-    // 不预览方形图片
-    noSquare: {
-      type: Boolean,
-      default: false
-    },
-    // 单文件大小限制
-    maxSize: {
-      type: Number,
-      default: 10240
-    },
-    // 语言类型
-    langType: {
-      type: String,
-      default: 'zh'
-    },
-    // 语言包
-    langExt: {
-      type: Object,
-      default: null
-    },
-    // 图片上传格式
-    imgFormat: {
-      type: String,
-      default: 'png'
-    },
-    // 是否支持跨域
-    withCredentials: {
-      type: Boolean,
-      default: false
-    }
-  },
-  data() {
-    const { imgFormat, langType, langExt, width, height } = this
-    let isSupported = true
-    const allowImgFormat = ['jpg', 'png']
-    const tempImgFormat =
-      allowImgFormat.indexOf(imgFormat) === -1 ? 'jpg' : imgFormat
-    const lang = language[langType] ? language[langType] : language['en']
-    const mime = mimes[tempImgFormat]
-    // 规范图片格式
-    this.imgFormat = tempImgFormat
-    if (langExt) {
-      Object.assign(lang, langExt)
-    }
-    if (typeof FormData !== 'function') {
-      isSupported = false
-    }
-    return {
-      // 图片的mime
-      mime,
-      // 语言包
-      lang,
-      // 浏览器是否支持该控件
-      isSupported,
-      // 浏览器是否支持触屏事件
-      // eslint-disable-next-line no-prototype-builtins
-      isSupportTouch: document.hasOwnProperty('ontouchstart'),
-      // 步骤
-      step: 1, // 1选择文件 2剪裁 3上传
-      // 上传状态及进度
-      loading: 0, // 0未开始 1正在 2成功 3错误
-      progress: 0,
-      // 是否有错误及错误信息
-      hasError: false,
-      errorMsg: '',
-      // 需求图宽高比
-      ratio: width / height,
-      // 原图地址、生成图片地址
-      sourceImg: null,
-      sourceImgUrl: '',
-      createImgUrl: '',
-      // 原图片拖动事件初始值
-      sourceImgMouseDown: {
-        on: false,
-        mX: 0, // 鼠标按下的坐标
-        mY: 0,
-        x: 0, // scale原图坐标
-        y: 0
-      },
-      // 生成图片预览的容器大小
-      previewContainer: {
-        width: 100,
-        height: 100
-      },
-      // 原图容器宽高
-      sourceImgContainer: {
-        // sic
-        width: 240,
-        height: 184 // 如果生成图比例与此一致会出现bug,先改成特殊的格式吧,哈哈哈
-      },
-      // 原图展示属性
-      scale: {
-        zoomAddOn: false, // 按钮缩放事件开启
-        zoomSubOn: false, // 按钮缩放事件开启
-        range: 1, // 最大100
-        rotateLeft: false, // 按钮向左旋转事件开启
-        rotateRight: false, // 按钮向右旋转事件开启
-        degree: 0, // 旋转度数
-        x: 0,
-        y: 0,
-        width: 0,
-        height: 0,
-        maxWidth: 0,
-        maxHeight: 0,
-        minWidth: 0, // 最宽
-        minHeight: 0,
-        naturalWidth: 0, // 原宽
-        naturalHeight: 0
-      }
-    }
-  },
-  computed: {
-    // 进度条样式
-    progressStyle() {
-      const { progress } = this
-      return {
-        width: progress + '%'
-      }
-    },
-    // 原图样式
-    sourceImgStyle() {
-      const { scale, sourceImgMasking } = this
-      const top = scale.y + sourceImgMasking.y + 'px'
-      const left = scale.x + sourceImgMasking.x + 'px'
-      return {
-        top,
-        left,
-        width: scale.width + 'px',
-        height: scale.height + 'px',
-        transform: 'rotate(' + scale.degree + 'deg)', // 旋转时 左侧原始图旋转样式
-        '-ms-transform': 'rotate(' + scale.degree + 'deg)', // 兼容IE9
-        '-moz-transform': 'rotate(' + scale.degree + 'deg)', // 兼容FireFox
-        '-webkit-transform': 'rotate(' + scale.degree + 'deg)', // 兼容Safari 和 chrome
-        '-o-transform': 'rotate(' + scale.degree + 'deg)' // 兼容 Opera
-      }
-    },
-    // 原图蒙版属性
-    sourceImgMasking() {
-      const { width, height, ratio, sourceImgContainer } = this
-      const sic = sourceImgContainer
-      const sicRatio = sic.width / sic.height // 原图容器宽高比
-      let x = 0
-      let y = 0
-      let w = sic.width
-      let h = sic.height
-      let scale = 1
-      if (ratio < sicRatio) {
-        scale = sic.height / height
-        w = sic.height * ratio
-        x = (sic.width - w) / 2
-      }
-      if (ratio > sicRatio) {
-        scale = sic.width / width
-        h = sic.width / ratio
-        y = (sic.height - h) / 2
-      }
-      return {
-        scale, // 蒙版相对需求宽高的缩放
-        x,
-        y,
-        width: w,
-        height: h
-      }
-    },
-    // 原图遮罩样式
-    sourceImgShadeStyle() {
-      const { sourceImgMasking, sourceImgContainer } = this
-      const sic = sourceImgContainer
-      const sim = sourceImgMasking
-      const w =
-        sim.width === sic.width ? sim.width : (sic.width - sim.width) / 2
-      const h =
-        sim.height === sic.height ? sim.height : (sic.height - sim.height) / 2
-      return {
-        width: w + 'px',
-        height: h + 'px'
-      }
-    },
-    previewStyle() {
-      const { ratio, previewContainer } = this
-      const pc = previewContainer
-      let w = pc.width
-      let h = pc.height
-      const pcRatio = w / h
-      if (ratio < pcRatio) {
-        w = pc.height * ratio
-      }
-      if (ratio > pcRatio) {
-        h = pc.width / ratio
-      }
-      return {
-        width: w + 'px',
-        height: h + 'px'
-      }
-    }
-  },
-  watch: {
-    value(newValue) {
-      if (newValue && this.loading !== 1) {
-        this.reset()
-      }
-    }
-  },
-  created() {
-    // 绑定按键esc隐藏此插件事件
-    document.addEventListener('keyup', this.closeHandler)
-  },
-  destroyed() {
-    document.removeEventListener('keyup', this.closeHandler)
-  },
-  methods: {
-    // 点击波纹效果
-    ripple(e) {
-      effectRipple(e)
-    },
-    // 关闭控件
-    off() {
-      setTimeout(() => {
-        this.$emit('input', false)
-        this.$emit('close')
-        if (this.step === 3 && this.loading === 2) {
-          this.setStep(1)
-        }
-      }, 200)
-    },
-    // 设置步骤
-    setStep(no) {
-      // 延时是为了显示动画效果呢,哈哈哈
-      setTimeout(() => {
-        this.step = no
-      }, 200)
-    },
-    /* 图片选择区域函数绑定
-     ---------------------------------------------------------------*/
-    preventDefault(e) {
-      e.preventDefault()
-      return false
-    },
-    handleClick(e) {
-      if (this.loading !== 1) {
-        if (e.target !== this.$refs.fileinput) {
-          e.preventDefault()
-          if (document.activeElement !== this.$refs) {
-            this.$refs.fileinput.click()
-          }
-        }
-      }
-    },
-    handleChange(e) {
-      e.preventDefault()
-      if (this.loading !== 1) {
-        const files = e.target.files || e.dataTransfer.files
-        this.reset()
-        if (this.checkFile(files[0])) {
-          this.setSourceImg(files[0])
-        }
-      }
-    },
-    /* ---------------------------------------------------------------*/
-    // 检测选择的文件是否合适
-    checkFile(file) {
-      const { lang, maxSize } = this
-      // 仅限图片
-      if (file.type.indexOf('image') === -1) {
-        this.hasError = true
-        this.errorMsg = lang.error.onlyImg
-        return false
-      }
-      // 超出大小
-      if (file.size / 1024 > maxSize) {
-        this.hasError = true
-        this.errorMsg = lang.error.outOfSize + maxSize + 'kb'
-        return false
-      }
-      return true
-    },
-    // 重置控件
-    reset() {
-      this.loading = 0
-      this.hasError = false
-      this.errorMsg = ''
-      this.progress = 0
-    },
-    // 设置图片源
-    setSourceImg(file) {
-      const fr = new FileReader()
-      fr.onload = e => {
-        this.sourceImgUrl = fr.result
-        this.startCrop()
-      }
-      fr.readAsDataURL(file)
-    },
-    // 剪裁前准备工作
-    startCrop() {
-      const {
-        width,
-        height,
-        ratio,
-        scale,
-        sourceImgUrl,
-        sourceImgMasking,
-        lang
-      } = this
-      const sim = sourceImgMasking
-      const img = new Image()
-      img.src = sourceImgUrl
-      img.onload = () => {
-        const nWidth = img.naturalWidth
-        const nHeight = img.naturalHeight
-        const nRatio = nWidth / nHeight
-        let w = sim.width
-        let h = sim.height
-        let x = 0
-        let y = 0
-        // 图片像素不达标
-        if (nWidth < width || nHeight < height) {
-          this.hasError = true
-          this.errorMsg = lang.error.lowestPx + width + '*' + height
-          return false
-        }
-        if (ratio > nRatio) {
-          h = w / nRatio
-          y = (sim.height - h) / 2
-        }
-        if (ratio < nRatio) {
-          w = h * nRatio
-          x = (sim.width - w) / 2
-        }
-        scale.range = 0
-        scale.x = x
-        scale.y = y
-        scale.width = w
-        scale.height = h
-        scale.degree = 0
-        scale.minWidth = w
-        scale.minHeight = h
-        scale.maxWidth = nWidth * sim.scale
-        scale.maxHeight = nHeight * sim.scale
-        scale.naturalWidth = nWidth
-        scale.naturalHeight = nHeight
-        this.sourceImg = img
-        this.createImg()
-        this.setStep(2)
-      }
-    },
-    // 鼠标按下图片准备移动
-    imgStartMove(e) {
-      e.preventDefault()
-      // 支持触摸事件,则鼠标事件无效
-      if (this.isSupportTouch && !e.targetTouches) {
-        return false
-      }
-      const et = e.targetTouches ? e.targetTouches[0] : e
-      const { sourceImgMouseDown, scale } = this
-      const simd = sourceImgMouseDown
-      simd.mX = et.screenX
-      simd.mY = et.screenY
-      simd.x = scale.x
-      simd.y = scale.y
-      simd.on = true
-    },
-    // 鼠标按下状态下移动,图片移动
-    imgMove(e) {
-      e.preventDefault()
-      // 支持触摸事件,则鼠标事件无效
-      if (this.isSupportTouch && !e.targetTouches) {
-        return false
-      }
-      const et = e.targetTouches ? e.targetTouches[0] : e
-      const {
-        sourceImgMouseDown: { on, mX, mY, x, y },
-        scale,
-        sourceImgMasking
-      } = this
-      const sim = sourceImgMasking
-      const nX = et.screenX
-      const nY = et.screenY
-      const dX = nX - mX
-      const dY = nY - mY
-      let rX = x + dX
-      let rY = y + dY
-      if (!on) return
-      if (rX > 0) {
-        rX = 0
-      }
-      if (rY > 0) {
-        rY = 0
-      }
-      if (rX < sim.width - scale.width) {
-        rX = sim.width - scale.width
-      }
-      if (rY < sim.height - scale.height) {
-        rY = sim.height - scale.height
-      }
-      scale.x = rX
-      scale.y = rY
-    },
-    // 按钮按下开始向右旋转
-    startRotateRight(e) {
-      const { scale } = this
-      scale.rotateRight = true
-      const rotate = () => {
-        if (scale.rotateRight) {
-          const degree = ++scale.degree
-          this.createImg(degree)
-          setTimeout(function() {
-            rotate()
-          }, 60)
-        }
-      }
-      rotate()
-    },
-    // 按钮按下开始向左旋转
-    startRotateLeft(e) {
-      const { scale } = this
-      scale.rotateLeft = true
-      const rotate = () => {
-        if (scale.rotateLeft) {
-          const degree = --scale.degree
-          this.createImg(degree)
-          setTimeout(function() {
-            rotate()
-          }, 60)
-        }
-      }
-      rotate()
-    },
-    // 停止旋转
-    endRotate() {
-      const { scale } = this
-      scale.rotateLeft = false
-      scale.rotateRight = false
-    },
-    // 按钮按下开始放大
-    startZoomAdd(e) {
-      const { scale } = this
-      scale.zoomAddOn = true
-      const zoom = () => {
-        if (scale.zoomAddOn) {
-          const range = scale.range >= 100 ? 100 : ++scale.range
-          this.zoomImg(range)
-          setTimeout(function() {
-            zoom()
-          }, 60)
-        }
-      }
-      zoom()
-    },
-    // 按钮松开或移开取消放大
-    endZoomAdd(e) {
-      this.scale.zoomAddOn = false
-    },
-    // 按钮按下开始缩小
-    startZoomSub(e) {
-      const { scale } = this
-      scale.zoomSubOn = true
-      const zoom = () => {
-        if (scale.zoomSubOn) {
-          const range = scale.range <= 0 ? 0 : --scale.range
-          this.zoomImg(range)
-          setTimeout(function() {
-            zoom()
-          }, 60)
-        }
-      }
-      zoom()
-    },
-    // 按钮松开或移开取消缩小
-    endZoomSub(e) {
-      const { scale } = this
-      scale.zoomSubOn = false
-    },
-    zoomChange(e) {
-      this.zoomImg(e.target.value)
-    },
-    // 缩放原图
-    zoomImg(newRange) {
-      const { sourceImgMasking, scale } = this
-      const {
-        maxWidth,
-        maxHeight,
-        minWidth,
-        minHeight,
-        width,
-        height,
-        x,
-        y
-      } = scale
-      const sim = sourceImgMasking
-      // 蒙版宽高
-      const sWidth = sim.width
-      const sHeight = sim.height
-      // 新宽高
-      const nWidth = minWidth + ((maxWidth - minWidth) * newRange) / 100
-      const nHeight = minHeight + ((maxHeight - minHeight) * newRange) / 100
-      // 新坐标(根据蒙版中心点缩放)
-      let nX = sWidth / 2 - (nWidth / width) * (sWidth / 2 - x)
-      let nY = sHeight / 2 - (nHeight / height) * (sHeight / 2 - y)
-      // 判断新坐标是否超过蒙版限制
-      if (nX > 0) {
-        nX = 0
-      }
-      if (nY > 0) {
-        nY = 0
-      }
-      if (nX < sWidth - nWidth) {
-        nX = sWidth - nWidth
-      }
-      if (nY < sHeight - nHeight) {
-        nY = sHeight - nHeight
-      }
-      // 赋值处理
-      scale.x = nX
-      scale.y = nY
-      scale.width = nWidth
-      scale.height = nHeight
-      scale.range = newRange
-      setTimeout(() => {
-        if (scale.range === newRange) {
-          this.createImg()
-        }
-      }, 300)
-    },
-    // 生成需求图片
-    createImg(e) {
-      const {
-        mime,
-        sourceImg,
-        scale: { x, y, width, height, degree },
-        sourceImgMasking: { scale }
-      } = this
-      const canvas = this.$refs.canvas
-      const ctx = canvas.getContext('2d')
-      if (e) {
-        // 取消鼠标按下移动状态
-        this.sourceImgMouseDown.on = false
-      }
-      canvas.width = this.width
-      canvas.height = this.height
-      ctx.clearRect(0, 0, this.width, this.height)
-      // 将透明区域设置为白色底边
-      ctx.fillStyle = '#fff'
-      ctx.fillRect(0, 0, this.width, this.height)
-      ctx.translate(this.width * 0.5, this.height * 0.5)
-      ctx.rotate((Math.PI * degree) / 180)
-      ctx.translate(-this.width * 0.5, -this.height * 0.5)
-      ctx.drawImage(
-        sourceImg,
-        x / scale,
-        y / scale,
-        width / scale,
-        height / scale
-      )
-      this.createImgUrl = canvas.toDataURL(mime)
-    },
-    prepareUpload() {
-      const { url, createImgUrl, field, ki } = this
-      this.$emit('crop-success', createImgUrl, field, ki)
-      if (typeof url === 'string' && url) {
-        this.upload()
-      } else {
-        this.off()
-      }
-    },
-    // 上传图片
-    upload() {
-      const {
-        lang,
-        imgFormat,
-        mime,
-        url,
-        params,
-        field,
-        ki,
-        createImgUrl
-      } = this
-      const fmData = new FormData()
-      fmData.append(
-        field,
-        data2blob(createImgUrl, mime),
-        field + '.' + imgFormat
-      )
-      // 添加其他参数
-      if (typeof params === 'object' && params) {
-        Object.keys(params).forEach(k => {
-          fmData.append(k, params[k])
-        })
-      }
-      // 监听进度回调
-      // const uploadProgress = (event) => {
-      //   if (event.lengthComputable) {
-      //     this.progress = 100 * Math.round(event.loaded) / event.total
-      //   }
-      // }
-      // 上传文件
-      this.reset()
-      this.loading = 1
-      this.setStep(3)
-      request({
-        url,
-        method: 'post',
-        data: fmData
-      })
-        .then(resData => {
-          this.loading = 2
-          this.$emit('crop-upload-success', resData.data)
-        })
-        .catch(err => {
-          if (this.value) {
-            this.loading = 3
-            this.hasError = true
-            this.errorMsg = lang.fail
-            this.$emit('crop-upload-fail', err, field, ki)
-          }
-        })
-    },
-    closeHandler(e) {
-      if (this.value && (e.key === 'Escape' || e.keyCode === 27)) {
-        this.off()
-      }
-    }
-  }
-}
-</script>
-
-<style lang="scss">
-@charset "UTF-8";
-@-webkit-keyframes vicp_progress {
-  0% {
-    background-position-y: 0;
-  }
-  100% {
-    background-position-y: 40px;
-  }
-}
-@keyframes vicp_progress {
-  0% {
-    background-position-y: 0;
-  }
-  100% {
-    background-position-y: 40px;
-  }
-}
-@-webkit-keyframes vicp {
-  0% {
-    opacity: 0;
-    -webkit-transform: scale(0) translatey(-60px);
-    transform: scale(0) translatey(-60px);
-  }
-  100% {
-    opacity: 1;
-    -webkit-transform: scale(1) translatey(0);
-    transform: scale(1) translatey(0);
-  }
-}
-@keyframes vicp {
-  0% {
-    opacity: 0;
-    -webkit-transform: scale(0) translatey(-60px);
-    transform: scale(0) translatey(-60px);
-  }
-  100% {
-    opacity: 1;
-    -webkit-transform: scale(1) translatey(0);
-    transform: scale(1) translatey(0);
-  }
-}
-.vue-image-crop-upload {
-  position: fixed;
-  display: block;
-  -webkit-box-sizing: border-box;
-  box-sizing: border-box;
-  z-index: 10000;
-  top: 0;
-  bottom: 0;
-  left: 0;
-  right: 0;
-  width: 100%;
-  height: 100%;
-  background-color: rgba(0, 0, 0, 0.65);
-  -webkit-tap-highlight-color: transparent;
-  -moz-tap-highlight-color: transparent;
-}
-.vue-image-crop-upload .vicp-wrap {
-  -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
-  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
-  position: fixed;
-  display: block;
-  -webkit-box-sizing: border-box;
-  box-sizing: border-box;
-  z-index: 10000;
-  top: 0;
-  bottom: 0;
-  left: 0;
-  right: 0;
-  margin: auto;
-  width: 600px;
-  height: 330px;
-  padding: 25px;
-  background-color: #fff;
-  border-radius: 2px;
-  -webkit-animation: vicp 0.12s ease-in;
-  animation: vicp 0.12s ease-in;
-}
-.vue-image-crop-upload .vicp-wrap .vicp-close {
-  position: absolute;
-  right: -30px;
-  top: -30px;
-}
-.vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4 {
-  position: relative;
-  display: block;
-  width: 30px;
-  height: 30px;
-  cursor: pointer;
-  -webkit-transition: -webkit-transform 0.18s;
-  transition: -webkit-transform 0.18s;
-  transition: transform 0.18s;
-  transition: transform 0.18s, -webkit-transform 0.18s;
-  -webkit-transform: rotate(0);
-  -ms-transform: rotate(0);
-  transform: rotate(0);
-}
-.vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4::after,
-.vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4::before {
-  -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
-  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
-  content: "";
-  position: absolute;
-  top: 12px;
-  left: 4px;
-  width: 20px;
-  height: 3px;
-  -webkit-transform: rotate(45deg);
-  -ms-transform: rotate(45deg);
-  transform: rotate(45deg);
-  background-color: #fff;
-}
-.vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4::after {
-  -webkit-transform: rotate(-45deg);
-  -ms-transform: rotate(-45deg);
-  transform: rotate(-45deg);
-}
-.vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4:hover {
-  -webkit-transform: rotate(90deg);
-  -ms-transform: rotate(90deg);
-  transform: rotate(90deg);
-}
-.vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area {
-  position: relative;
-  -webkit-box-sizing: border-box;
-  box-sizing: border-box;
-  padding: 35px;
-  height: 170px;
-  background-color: rgba(0, 0, 0, 0.03);
-  text-align: center;
-  border: 1px dashed rgba(0, 0, 0, 0.08);
-  overflow: hidden;
-}
-.vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-icon1 {
-  display: block;
-  margin: 0 auto 6px;
-  width: 42px;
-  height: 42px;
-  overflow: hidden;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step1
-  .vicp-drop-area
-  .vicp-icon1
-  .vicp-icon1-arrow {
-  display: block;
-  margin: 0 auto;
-  width: 0;
-  height: 0;
-  border-bottom: 14.7px solid rgba(0, 0, 0, 0.3);
-  border-left: 14.7px solid transparent;
-  border-right: 14.7px solid transparent;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step1
-  .vicp-drop-area
-  .vicp-icon1
-  .vicp-icon1-body {
-  display: block;
-  width: 12.6px;
-  height: 14.7px;
-  margin: 0 auto;
-  background-color: rgba(0, 0, 0, 0.3);
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step1
-  .vicp-drop-area
-  .vicp-icon1
-  .vicp-icon1-bottom {
-  -webkit-box-sizing: border-box;
-  box-sizing: border-box;
-  display: block;
-  height: 12.6px;
-  border: 6px solid rgba(0, 0, 0, 0.3);
-  border-top: none;
-}
-.vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-hint {
-  display: block;
-  padding: 15px;
-  font-size: 14px;
-  color: #666;
-  line-height: 30px;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step1
-  .vicp-drop-area
-  .vicp-no-supported-hint {
-  display: block;
-  position: absolute;
-  top: 0;
-  left: 0;
-  padding: 30px;
-  width: 100%;
-  height: 60px;
-  line-height: 30px;
-  background-color: #eee;
-  text-align: center;
-  color: #666;
-  font-size: 14px;
-}
-.vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area:hover {
-  cursor: pointer;
-  border-color: rgba(0, 0, 0, 0.1);
-  background-color: rgba(0, 0, 0, 0.05);
-}
-.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop {
-  overflow: hidden;
-}
-.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left {
-  float: left;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-img-container {
-  position: relative;
-  display: block;
-  width: 240px;
-  height: 180px;
-  background-color: #e5e5e0;
-  overflow: hidden;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-img-container
-  .vicp-img {
-  position: absolute;
-  display: block;
-  cursor: move;
-  -webkit-user-select: none;
-  -moz-user-select: none;
-  -ms-user-select: none;
-  user-select: none;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-img-container
-  .vicp-img-shade {
-  -webkit-box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
-  box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
-  position: absolute;
-  background-color: rgba(241, 242, 243, 0.8);
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-img-container
-  .vicp-img-shade.vicp-img-shade-1 {
-  top: 0;
-  left: 0;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-img-container
-  .vicp-img-shade.vicp-img-shade-2 {
-  bottom: 0;
-  right: 0;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-rotate {
-  position: relative;
-  width: 240px;
-  height: 18px;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-rotate
-  i {
-  display: block;
-  width: 18px;
-  height: 18px;
-  border-radius: 100%;
-  line-height: 18px;
-  text-align: center;
-  font-size: 12px;
-  font-weight: bold;
-  background-color: rgba(0, 0, 0, 0.08);
-  color: #fff;
-  overflow: hidden;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-rotate
-  i:hover {
-  -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
-  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
-  cursor: pointer;
-  background-color: rgba(0, 0, 0, 0.14);
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-rotate
-  i:first-child {
-  float: left;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-rotate
-  i:last-child {
-  float: right;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range {
-  position: relative;
-  margin: 30px 0 10px 0;
-  width: 240px;
-  height: 18px;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  .vicp-icon5,
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  .vicp-icon6 {
-  position: absolute;
-  top: 0;
-  width: 18px;
-  height: 18px;
-  border-radius: 100%;
-  background-color: rgba(0, 0, 0, 0.08);
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  .vicp-icon5:hover,
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  .vicp-icon6:hover {
-  -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
-  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
-  cursor: pointer;
-  background-color: rgba(0, 0, 0, 0.14);
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  .vicp-icon5 {
-  left: 0;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  .vicp-icon5::before {
-  position: absolute;
-  content: "";
-  display: block;
-  left: 3px;
-  top: 8px;
-  width: 12px;
-  height: 2px;
-  background-color: #fff;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  .vicp-icon6 {
-  right: 0;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  .vicp-icon6::before {
-  position: absolute;
-  content: "";
-  display: block;
-  left: 3px;
-  top: 8px;
-  width: 12px;
-  height: 2px;
-  background-color: #fff;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  .vicp-icon6::after {
-  position: absolute;
-  content: "";
-  display: block;
-  top: 3px;
-  left: 8px;
-  width: 2px;
-  height: 12px;
-  background-color: #fff;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  input[type="range"] {
-  display: block;
-  padding-top: 5px;
-  margin: 0 auto;
-  width: 180px;
-  height: 8px;
-  vertical-align: top;
-  background: transparent;
-  -webkit-appearance: none;
-  -moz-appearance: none;
-  appearance: none;
-  cursor: pointer;
-  /* 滑块
-               ---------------------------------------------------------------*/
-  /* 轨道
-               ---------------------------------------------------------------*/
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  input[type="range"]:focus {
-  outline: none;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  input[type="range"]::-webkit-slider-thumb {
-  -webkit-box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
-  box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
-  -webkit-appearance: none;
-  appearance: none;
-  margin-top: -3px;
-  width: 12px;
-  height: 12px;
-  background-color: #61c091;
-  border-radius: 100%;
-  border: none;
-  -webkit-transition: 0.2s;
-  transition: 0.2s;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  input[type="range"]::-moz-range-thumb {
-  box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
-  -moz-appearance: none;
-  appearance: none;
-  width: 12px;
-  height: 12px;
-  background-color: #61c091;
-  border-radius: 100%;
-  border: none;
-  -webkit-transition: 0.2s;
-  transition: 0.2s;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  input[type="range"]::-ms-thumb {
-  box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
-  appearance: none;
-  width: 12px;
-  height: 12px;
-  background-color: #61c091;
-  border: none;
-  border-radius: 100%;
-  -webkit-transition: 0.2s;
-  transition: 0.2s;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  input[type="range"]:active::-moz-range-thumb {
-  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
-  width: 14px;
-  height: 14px;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  input[type="range"]:active::-ms-thumb {
-  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
-  width: 14px;
-  height: 14px;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  input[type="range"]:active::-webkit-slider-thumb {
-  -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
-  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
-  margin-top: -4px;
-  width: 14px;
-  height: 14px;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  input[type="range"]::-webkit-slider-runnable-track {
-  -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
-  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
-  width: 100%;
-  height: 6px;
-  cursor: pointer;
-  border-radius: 2px;
-  border: none;
-  background-color: rgba(68, 170, 119, 0.3);
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  input[type="range"]::-moz-range-track {
-  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
-  width: 100%;
-  height: 6px;
-  cursor: pointer;
-  border-radius: 2px;
-  border: none;
-  background-color: rgba(68, 170, 119, 0.3);
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  input[type="range"]::-ms-track {
-  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
-  width: 100%;
-  cursor: pointer;
-  background: transparent;
-  border-color: transparent;
-  color: transparent;
-  height: 6px;
-  border-radius: 2px;
-  border: none;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  input[type="range"]::-ms-fill-lower {
-  background-color: rgba(68, 170, 119, 0.3);
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  input[type="range"]::-ms-fill-upper {
-  background-color: rgba(68, 170, 119, 0.15);
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  input[type="range"]:focus::-webkit-slider-runnable-track {
-  background-color: rgba(68, 170, 119, 0.5);
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  input[type="range"]:focus::-moz-range-track {
-  background-color: rgba(68, 170, 119, 0.5);
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  input[type="range"]:focus::-ms-fill-lower {
-  background-color: rgba(68, 170, 119, 0.45);
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-left
-  .vicp-range
-  input[type="range"]:focus::-ms-fill-upper {
-  background-color: rgba(68, 170, 119, 0.25);
-}
-.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right {
-  float: right;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-right
-  .vicp-preview {
-  height: 150px;
-  overflow: hidden;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-right
-  .vicp-preview
-  .vicp-preview-item {
-  position: relative;
-  padding: 5px;
-  width: 100px;
-  height: 100px;
-  float: left;
-  margin-right: 16px;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-right
-  .vicp-preview
-  .vicp-preview-item
-  span {
-  position: absolute;
-  bottom: -30px;
-  width: 100%;
-  font-size: 14px;
-  color: #bbb;
-  display: block;
-  text-align: center;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-right
-  .vicp-preview
-  .vicp-preview-item
-  img {
-  position: absolute;
-  display: block;
-  top: 0;
-  bottom: 0;
-  left: 0;
-  right: 0;
-  margin: auto;
-  padding: 3px;
-  background-color: #fff;
-  border: 1px solid rgba(0, 0, 0, 0.15);
-  overflow: hidden;
-  -webkit-user-select: none;
-  -moz-user-select: none;
-  -ms-user-select: none;
-  user-select: none;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-right
-  .vicp-preview
-  .vicp-preview-item.vicp-preview-item-circle {
-  margin-right: 0;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step2
-  .vicp-crop
-  .vicp-crop-right
-  .vicp-preview
-  .vicp-preview-item.vicp-preview-item-circle
-  img {
-  border-radius: 100%;
-}
-.vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload {
-  position: relative;
-  -webkit-box-sizing: border-box;
-  box-sizing: border-box;
-  padding: 35px;
-  height: 170px;
-  background-color: rgba(0, 0, 0, 0.03);
-  text-align: center;
-  border: 1px dashed #ddd;
-}
-.vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-loading {
-  display: block;
-  padding: 15px;
-  font-size: 16px;
-  color: #999;
-  line-height: 30px;
-}
-.vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-progress-wrap {
-  margin-top: 12px;
-  background-color: rgba(0, 0, 0, 0.08);
-  border-radius: 3px;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step3
-  .vicp-upload
-  .vicp-progress-wrap
-  .vicp-progress {
-  position: relative;
-  display: block;
-  height: 5px;
-  border-radius: 3px;
-  background-color: #4a7;
-  -webkit-box-shadow: 0 2px 6px 0 rgba(68, 170, 119, 0.3);
-  box-shadow: 0 2px 6px 0 rgba(68, 170, 119, 0.3);
-  -webkit-transition: width 0.15s linear;
-  transition: width 0.15s linear;
-  background-image: -webkit-linear-gradient(
-    135deg,
-    rgba(255, 255, 255, 0.2) 25%,
-    transparent 25%,
-    transparent 50%,
-    rgba(255, 255, 255, 0.2) 50%,
-    rgba(255, 255, 255, 0.2) 75%,
-    transparent 75%,
-    transparent
-  );
-  background-image: linear-gradient(
-    -45deg,
-    rgba(255, 255, 255, 0.2) 25%,
-    transparent 25%,
-    transparent 50%,
-    rgba(255, 255, 255, 0.2) 50%,
-    rgba(255, 255, 255, 0.2) 75%,
-    transparent 75%,
-    transparent
-  );
-  background-size: 40px 40px;
-  -webkit-animation: vicp_progress 0.5s linear infinite;
-  animation: vicp_progress 0.5s linear infinite;
-}
-.vue-image-crop-upload
-  .vicp-wrap
-  .vicp-step3
-  .vicp-upload
-  .vicp-progress-wrap
-  .vicp-progress::after {
-  content: "";
-  position: absolute;
-  display: block;
-  top: -3px;
-  right: -3px;
-  width: 9px;
-  height: 9px;
-  border: 1px solid rgba(245, 246, 247, 0.7);
-  -webkit-box-shadow: 0 1px 4px 0 rgba(68, 170, 119, 0.7);
-  box-shadow: 0 1px 4px 0 rgba(68, 170, 119, 0.7);
-  border-radius: 100%;
-  background-color: #4a7;
-}
-.vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-error,
-.vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-success {
-  height: 100px;
-  line-height: 100px;
-}
-.vue-image-crop-upload .vicp-wrap .vicp-operate {
-  position: absolute;
-  right: 20px;
-  bottom: 20px;
-}
-.vue-image-crop-upload .vicp-wrap .vicp-operate a {
-  position: relative;
-  float: left;
-  display: block;
-  margin-left: 10px;
-  width: 100px;
-  height: 36px;
-  line-height: 36px;
-  text-align: center;
-  cursor: pointer;
-  font-size: 14px;
-  color: #4a7;
-  border-radius: 2px;
-  overflow: hidden;
-  -webkit-user-select: none;
-  -moz-user-select: none;
-  -ms-user-select: none;
-  user-select: none;
-}
-.vue-image-crop-upload .vicp-wrap .vicp-operate a:hover {
-  background-color: rgba(0, 0, 0, 0.03);
-}
-.vue-image-crop-upload .vicp-wrap .vicp-error,
-.vue-image-crop-upload .vicp-wrap .vicp-success {
-  display: block;
-  font-size: 14px;
-  line-height: 24px;
-  height: 24px;
-  color: #d10;
-  text-align: center;
-  vertical-align: top;
-}
-.vue-image-crop-upload .vicp-wrap .vicp-success {
-  color: #4a7;
-}
-.vue-image-crop-upload .vicp-wrap .vicp-icon3 {
-  position: relative;
-  display: inline-block;
-  width: 20px;
-  height: 20px;
-  top: 4px;
-}
-.vue-image-crop-upload .vicp-wrap .vicp-icon3::after {
-  position: absolute;
-  top: 3px;
-  left: 6px;
-  width: 6px;
-  height: 10px;
-  border-width: 0 2px 2px 0;
-  border-color: #4a7;
-  border-style: solid;
-  -webkit-transform: rotate(45deg);
-  -ms-transform: rotate(45deg);
-  transform: rotate(45deg);
-  content: "";
-}
-.vue-image-crop-upload .vicp-wrap .vicp-icon2 {
-  position: relative;
-  display: inline-block;
-  width: 20px;
-  height: 20px;
-  top: 4px;
-}
-.vue-image-crop-upload .vicp-wrap .vicp-icon2::after,
-.vue-image-crop-upload .vicp-wrap .vicp-icon2::before {
-  content: "";
-  position: absolute;
-  top: 9px;
-  left: 4px;
-  width: 13px;
-  height: 2px;
-  background-color: #d10;
-  -webkit-transform: rotate(45deg);
-  -ms-transform: rotate(45deg);
-  transform: rotate(45deg);
-}
-.vue-image-crop-upload .vicp-wrap .vicp-icon2::after {
-  -webkit-transform: rotate(-45deg);
-  -ms-transform: rotate(-45deg);
-  transform: rotate(-45deg);
-}
-.e-ripple {
-  position: absolute;
-  border-radius: 100%;
-  background-color: rgba(0, 0, 0, 0.15);
-  background-clip: padding-box;
-  pointer-events: none;
-  -webkit-user-select: none;
-  -moz-user-select: none;
-  -ms-user-select: none;
-  user-select: none;
-  -webkit-transform: scale(0);
-  -ms-transform: scale(0);
-  transform: scale(0);
-  opacity: 1;
-}
-.e-ripple.z-active {
-  opacity: 0;
-  -webkit-transform: scale(2);
-  -ms-transform: scale(2);
-  transform: scale(2);
-  -webkit-transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
-  transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
-  transition: opacity 1.2s ease-out, transform 0.6s ease-out;
-  transition: opacity 1.2s ease-out, transform 0.6s ease-out,
-    -webkit-transform 0.6s ease-out;
-}
-</style>

+ 0 - 19
src/components/ImageCropper/utils/data2blob.js

@@ -1,19 +0,0 @@
-/**
- * database64文件格式转换为2进制
- *
- * @param  {[String]} data dataURL 的格式为 “data:image/png;base64,****”,逗号之前都是一些说明性的文字,我们只需要逗号之后的就行了
- * @param  {[String]} mime [description]
- * @return {[blob]}      [description]
- */
-export default function(data, mime) {
-  data = data.split(',')[1]
-  data = window.atob(data)
-  var ia = new Uint8Array(data.length)
-  for (var i = 0; i < data.length; i++) {
-    ia[i] = data.charCodeAt(i)
-  }
-  // canvas.toDataURL 返回的默认格式就是 image/png
-  return new Blob([ia], {
-    type: mime
-  })
-}

+ 0 - 39
src/components/ImageCropper/utils/effectRipple.js

@@ -1,39 +0,0 @@
-/**
- * 点击波纹效果
- *
- * @param  {[event]} e        [description]
- * @param  {[Object]} arg_opts [description]
- * @return {[bollean]}          [description]
- */
-export default function(e, arg_opts) {
-  var opts = Object.assign({
-    ele: e.target, // 波纹作用元素
-    type: 'hit', // hit点击位置扩散center中心点扩展
-    bgc: 'rgba(0, 0, 0, 0.15)' // 波纹颜色
-  }, arg_opts)
-  var target = opts.ele
-  if (target) {
-    var rect = target.getBoundingClientRect()
-    var ripple = target.querySelector('.e-ripple')
-    if (!ripple) {
-      ripple = document.createElement('span')
-      ripple.className = 'e-ripple'
-      ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px'
-      target.appendChild(ripple)
-    } else {
-      ripple.className = 'e-ripple'
-    }
-    switch (opts.type) {
-      case 'center':
-        ripple.style.top = (rect.height / 2 - ripple.offsetHeight / 2) + 'px'
-        ripple.style.left = (rect.width / 2 - ripple.offsetWidth / 2) + 'px'
-        break
-      default:
-        ripple.style.top = (e.pageY - rect.top - ripple.offsetHeight / 2 - document.body.scrollTop) + 'px'
-        ripple.style.left = (e.pageX - rect.left - ripple.offsetWidth / 2 - document.body.scrollLeft) + 'px'
-    }
-    ripple.style.backgroundColor = opts.bgc
-    ripple.className = 'e-ripple z-active'
-    return false
-  }
-}

+ 0 - 232
src/components/ImageCropper/utils/language.js

@@ -1,232 +0,0 @@
-export default {
-  zh: {
-    hint: '点击,或拖动图片至此处',
-    loading: '正在上传……',
-    noSupported: '浏览器不支持该功能,请使用IE10以上或其他现在浏览器!',
-    success: '上传成功',
-    fail: '图片上传失败',
-    preview: '头像预览',
-    btn: {
-      off: '取消',
-      close: '关闭',
-      back: '上一步',
-      save: '保存'
-    },
-    error: {
-      onlyImg: '仅限图片格式',
-      outOfSize: '单文件大小不能超过 ',
-      lowestPx: '图片最低像素为(宽*高):'
-    }
-  },
-  'zh-tw': {
-    hint: '點擊,或拖動圖片至此處',
-    loading: '正在上傳……',
-    noSupported: '瀏覽器不支持該功能,請使用IE10以上或其他現代瀏覽器!',
-    success: '上傳成功',
-    fail: '圖片上傳失敗',
-    preview: '頭像預覽',
-    btn: {
-      off: '取消',
-      close: '關閉',
-      back: '上一步',
-      save: '保存'
-    },
-    error: {
-      onlyImg: '僅限圖片格式',
-      outOfSize: '單文件大小不能超過 ',
-      lowestPx: '圖片最低像素為(寬*高):'
-    }
-  },
-  en: {
-    hint: 'Click or drag the file here to upload',
-    loading: 'Uploading…',
-    noSupported: 'Browser is not supported, please use IE10+ or other browsers',
-    success: 'Upload success',
-    fail: 'Upload failed',
-    preview: 'Preview',
-    btn: {
-      off: 'Cancel',
-      close: 'Close',
-      back: 'Back',
-      save: 'Save'
-    },
-    error: {
-      onlyImg: 'Image only',
-      outOfSize: 'Image exceeds size limit: ',
-      lowestPx: 'Image\'s size is too low. Expected at least: '
-    }
-  },
-  ro: {
-    hint: 'Atinge sau trage fișierul aici',
-    loading: 'Se încarcă',
-    noSupported: 'Browser-ul tău nu suportă acest feature. Te rugăm încearcă cu alt browser.',
-    success: 'S-a încărcat cu succes',
-    fail: 'A apărut o problemă la încărcare',
-    preview: 'Previzualizează',
-
-    btn: {
-      off: 'Anulează',
-      close: 'Închide',
-      back: 'Înapoi',
-      save: 'Salvează'
-    },
-
-    error: {
-      onlyImg: 'Doar imagini',
-      outOfSize: 'Imaginea depășește limita de: ',
-      loewstPx: 'Imaginea este prea mică; Minim: '
-    }
-  },
-  ru: {
-    hint: 'Нажмите, или перетащите файл в это окно',
-    loading: 'Загружаю……',
-    noSupported: 'Ваш браузер не поддерживается, пожалуйста, используйте IE10 + или другие браузеры',
-    success: 'Загрузка выполнена успешно',
-    fail: 'Ошибка загрузки',
-    preview: 'Предпросмотр',
-    btn: {
-      off: 'Отменить',
-      close: 'Закрыть',
-      back: 'Назад',
-      save: 'Сохранить'
-    },
-    error: {
-      onlyImg: 'Только изображения',
-      outOfSize: 'Изображение превышает предельный размер: ',
-      lowestPx: 'Минимальный размер изображения: '
-    }
-  },
-  'pt-br': {
-    hint: 'Clique ou arraste o arquivo aqui para carregar',
-    loading: 'Carregando…',
-    noSupported: 'Browser não suportado, use o IE10+ ou outro browser',
-    success: 'Sucesso ao carregar imagem',
-    fail: 'Falha ao carregar imagem',
-    preview: 'Pré-visualizar',
-    btn: {
-      off: 'Cancelar',
-      close: 'Fechar',
-      back: 'Voltar',
-      save: 'Salvar'
-    },
-    error: {
-      onlyImg: 'Apenas imagens',
-      outOfSize: 'A imagem excede o limite de tamanho: ',
-      lowestPx: 'O tamanho da imagem é muito pequeno. Tamanho mínimo: '
-    }
-  },
-  fr: {
-    hint: 'Cliquez ou glissez le fichier ici.',
-    loading: 'Téléchargement…',
-    noSupported: 'Votre navigateur n\'est pas supporté. Utilisez IE10 + ou un autre navigateur s\'il vous plaît.',
-    success: 'Téléchargement réussit',
-    fail: 'Téléchargement echoué',
-    preview: 'Aperçu',
-    btn: {
-      off: 'Annuler',
-      close: 'Fermer',
-      back: 'Retour',
-      save: 'Enregistrer'
-    },
-    error: {
-      onlyImg: 'Image uniquement',
-      outOfSize: 'L\'image sélectionnée dépasse la taille maximum: ',
-      lowestPx: 'L\'image sélectionnée est trop petite. Dimensions attendues: '
-    }
-  },
-  nl: {
-    hint: 'Klik hier of sleep een afbeelding in dit vlak',
-    loading: 'Uploaden…',
-    noSupported: 'Je browser wordt helaas niet ondersteund. Gebruik IE10+ of een andere browser.',
-    success: 'Upload succesvol',
-    fail: 'Upload mislukt',
-    preview: 'Voorbeeld',
-    btn: {
-      off: 'Annuleren',
-      close: 'Sluiten',
-      back: 'Terug',
-      save: 'Opslaan'
-    },
-    error: {
-      onlyImg: 'Alleen afbeeldingen',
-      outOfSize: 'De afbeelding is groter dan: ',
-      lowestPx: 'De afbeelding is te klein! Minimale afmetingen: '
-    }
-  },
-  tr: {
-    hint: 'Tıkla veya yüklemek istediğini buraya sürükle',
-    loading: 'Yükleniyor…',
-    noSupported: 'Tarayıcı desteklenmiyor, lütfen IE10+ veya farklı tarayıcı kullanın',
-    success: 'Yükleme başarılı',
-    fail: 'Yüklemede hata oluştu',
-    preview: 'Önizle',
-    btn: {
-      off: 'İptal',
-      close: 'Kapat',
-      back: 'Geri',
-      save: 'Kaydet'
-    },
-    error: {
-      onlyImg: 'Sadece resim',
-      outOfSize: 'Resim yükleme limitini aşıyor: ',
-      lowestPx: 'Resmin boyutu çok küçük. En az olması gereken: '
-    }
-  },
-  'es-MX': {
-    hint: 'Selecciona o arrastra una imagen',
-    loading: 'Subiendo...',
-    noSupported: 'Tu navegador no es soportado, porfavor usa IE10+ u otros navegadores mas recientes',
-    success: 'Subido exitosamente',
-    fail: 'Sucedió un error',
-    preview: 'Vista previa',
-    btn: {
-      off: 'Cancelar',
-      close: 'Cerrar',
-      back: 'Atras',
-      save: 'Guardar'
-    },
-    error: {
-      onlyImg: 'Unicamente imagenes',
-      outOfSize: 'La imagen excede el tamaño maximo:',
-      lowestPx: 'La imagen es demasiado pequeño. Se espera por lo menos:'
-    }
-  },
-  de: {
-    hint: 'Klick hier oder zieh eine Datei hier rein zum Hochladen',
-    loading: 'Hochladen…',
-    noSupported: 'Browser wird nicht unterstützt, bitte verwende IE10+ oder andere Browser',
-    success: 'Upload erfolgreich',
-    fail: 'Upload fehlgeschlagen',
-    preview: 'Vorschau',
-    btn: {
-      off: 'Abbrechen',
-      close: 'Schließen',
-      back: 'Zurück',
-      save: 'Speichern'
-    },
-    error: {
-      onlyImg: 'Nur Bilder',
-      outOfSize: 'Das Bild ist zu groß: ',
-      lowestPx: 'Das Bild ist zu klein. Mindestens: '
-    }
-  },
-  ja: {
-    hint: 'クリック・ドラッグしてファイルをアップロード',
-    loading: 'アップロード中...',
-    noSupported: 'このブラウザは対応されていません。IE10+かその他の主要ブラウザをお使いください。',
-    success: 'アップロード成功',
-    fail: 'アップロード失敗',
-    preview: 'プレビュー',
-    btn: {
-      off: 'キャンセル',
-      close: '閉じる',
-      back: '戻る',
-      save: '保存'
-    },
-    error: {
-      onlyImg: '画像のみ',
-      outOfSize: '画像サイズが上限を超えています。上限: ',
-      lowestPx: '画像が小さすぎます。最小サイズ: '
-    }
-  }
-}

+ 0 - 7
src/components/ImageCropper/utils/mimes.js

@@ -1,7 +0,0 @@
-export default {
-  'jpg': 'image/jpeg',
-  'png': 'image/png',
-  'gif': 'image/gif',
-  'svg': 'image/svg+xml',
-  'psd': 'image/photoshop'
-}

+ 0 - 77
src/components/JsonEditor/index.vue

@@ -1,77 +0,0 @@
-<template>
-  <div class="json-editor">
-    <textarea ref="textarea" />
-  </div>
-</template>
-
-<script>
-import CodeMirror from 'codemirror'
-import 'codemirror/addon/lint/lint.css'
-import 'codemirror/lib/codemirror.css'
-import 'codemirror/theme/rubyblue.css'
-require('script-loader!jsonlint')
-import 'codemirror/mode/javascript/javascript'
-import 'codemirror/addon/lint/lint'
-import 'codemirror/addon/lint/json-lint'
-
-export default {
-  name: 'JsonEditor',
-  /* eslint-disable vue/require-prop-types */
-  props: ['value'],
-  data() {
-    return {
-      jsonEditor: false
-    }
-  },
-  watch: {
-    value(value) {
-      const editorValue = this.jsonEditor.getValue()
-      if (value !== editorValue) {
-        this.jsonEditor.setValue(JSON.stringify(this.value, null, 2))
-      }
-    }
-  },
-  mounted() {
-    this.jsonEditor = CodeMirror.fromTextArea(this.$refs.textarea, {
-      lineNumbers: true,
-      mode: 'application/json',
-      gutters: ['CodeMirror-lint-markers'],
-      theme: 'rubyblue',
-      lint: true
-    })
-
-    this.jsonEditor.setValue(JSON.stringify(this.value, null, 2))
-    this.jsonEditor.on('change', cm => {
-      this.$emit('changed', cm.getValue())
-      this.$emit('input', cm.getValue())
-    })
-  },
-  methods: {
-    getValue() {
-      return this.jsonEditor.getValue()
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.json-editor {
-  height: 100%;
-  position: relative;
-
-  ::v-deep {
-    .CodeMirror {
-      height: auto;
-      min-height: 300px;
-    }
-
-    .CodeMirror-scroll {
-      min-height: 300px;
-    }
-
-    .cm-s-rubyblue span.cm-string {
-      color: #F08047;
-    }
-  }
-}
-</style>

+ 0 - 99
src/components/Kanban/index.vue

@@ -1,99 +0,0 @@
-<template>
-  <div class="board-column">
-    <div class="board-column-header">
-      {{ headerText }}
-    </div>
-    <draggable
-      :list="list"
-      v-bind="$attrs"
-      class="board-column-content"
-      :set-data="setData"
-    >
-      <div v-for="element in list" :key="element.id" class="board-item">
-        {{ element.name }} {{ element.id }}
-      </div>
-    </draggable>
-  </div>
-</template>
-
-<script>
-import draggable from 'vuedraggable'
-
-export default {
-  name: 'DragKanbanDemo',
-  components: {
-    draggable
-  },
-  props: {
-    headerText: {
-      type: String,
-      default: 'Header'
-    },
-    options: {
-      type: Object,
-      default() {
-        return {}
-      }
-    },
-    list: {
-      type: Array,
-      default() {
-        return []
-      }
-    }
-  },
-  methods: {
-    setData(dataTransfer) {
-      // to avoid Firefox bug
-      // Detail see : https://github.com/RubaXa/Sortable/issues/1012
-      dataTransfer.setData('Text', '')
-    }
-  }
-}
-</script>
-<style lang="scss" scoped>
-.board-column {
-  min-width: 300px;
-  min-height: 100px;
-  height: auto;
-  overflow: hidden;
-  background: #f0f0f0;
-  border-radius: 3px;
-
-  .board-column-header {
-    height: 50px;
-    line-height: 50px;
-    overflow: hidden;
-    padding: 0 20px;
-    text-align: center;
-    background: #333;
-    color: #fff;
-    border-radius: 3px 3px 0 0;
-  }
-
-  .board-column-content {
-    height: auto;
-    overflow: hidden;
-    border: 10px solid transparent;
-    min-height: 60px;
-    display: flex;
-    justify-content: flex-start;
-    flex-direction: column;
-    align-items: center;
-
-    .board-item {
-      cursor: pointer;
-      width: 100%;
-      height: 64px;
-      margin: 5px 0;
-      background-color: #fff;
-      text-align: left;
-      line-height: 54px;
-      padding: 5px 10px;
-      box-sizing: border-box;
-      box-shadow: 0px 1px 3px 0 rgba(0, 0, 0, 0.2);
-    }
-  }
-}
-</style>
-

+ 0 - 360
src/components/MDinput/index.vue

@@ -1,360 +0,0 @@
-<template>
-  <div :class="computedClasses" class="material-input__component">
-    <div :class="{iconClass:icon}">
-      <i v-if="icon" :class="['el-icon-' + icon]" class="el-input__icon material-input__icon" />
-      <input
-        v-if="type === 'email'"
-        v-model="currentValue"
-        :name="name"
-        :placeholder="fillPlaceHolder"
-        :readonly="readonly"
-        :disabled="disabled"
-        :autocomplete="autoComplete"
-        :required="required"
-        type="email"
-        class="material-input"
-        @focus="handleMdFocus"
-        @blur="handleMdBlur"
-        @input="handleModelInput"
-      >
-      <input
-        v-if="type === 'url'"
-        v-model="currentValue"
-        :name="name"
-        :placeholder="fillPlaceHolder"
-        :readonly="readonly"
-        :disabled="disabled"
-        :autocomplete="autoComplete"
-        :required="required"
-        type="url"
-        class="material-input"
-        @focus="handleMdFocus"
-        @blur="handleMdBlur"
-        @input="handleModelInput"
-      >
-      <input
-        v-if="type === 'number'"
-        v-model="currentValue"
-        :name="name"
-        :placeholder="fillPlaceHolder"
-        :step="step"
-        :readonly="readonly"
-        :disabled="disabled"
-        :autocomplete="autoComplete"
-        :max="max"
-        :min="min"
-        :minlength="minlength"
-        :maxlength="maxlength"
-        :required="required"
-        type="number"
-        class="material-input"
-        @focus="handleMdFocus"
-        @blur="handleMdBlur"
-        @input="handleModelInput"
-      >
-      <input
-        v-if="type === 'password'"
-        v-model="currentValue"
-        :name="name"
-        :placeholder="fillPlaceHolder"
-        :readonly="readonly"
-        :disabled="disabled"
-        :autocomplete="autoComplete"
-        :max="max"
-        :min="min"
-        :required="required"
-        type="password"
-        class="material-input"
-        @focus="handleMdFocus"
-        @blur="handleMdBlur"
-        @input="handleModelInput"
-      >
-      <input
-        v-if="type === 'tel'"
-        v-model="currentValue"
-        :name="name"
-        :placeholder="fillPlaceHolder"
-        :readonly="readonly"
-        :disabled="disabled"
-        :autocomplete="autoComplete"
-        :required="required"
-        type="tel"
-        class="material-input"
-        @focus="handleMdFocus"
-        @blur="handleMdBlur"
-        @input="handleModelInput"
-      >
-      <input
-        v-if="type === 'text'"
-        v-model="currentValue"
-        :name="name"
-        :placeholder="fillPlaceHolder"
-        :readonly="readonly"
-        :disabled="disabled"
-        :autocomplete="autoComplete"
-        :minlength="minlength"
-        :maxlength="maxlength"
-        :required="required"
-        type="text"
-        class="material-input"
-        @focus="handleMdFocus"
-        @blur="handleMdBlur"
-        @input="handleModelInput"
-      >
-      <span class="material-input-bar" />
-      <label class="material-label">
-        <slot />
-      </label>
-    </div>
-  </div>
-</template>
-
-<script>
-// source:https://github.com/wemake-services/vue-material-input/blob/master/src/components/MaterialInput.vue
-
-export default {
-  name: 'MdInput',
-  props: {
-    /* eslint-disable */
-    icon: String,
-    name: String,
-    type: {
-      type: String,
-      default: 'text'
-    },
-    value: [String, Number],
-    placeholder: String,
-    readonly: Boolean,
-    disabled: Boolean,
-    min: String,
-    max: String,
-    step: String,
-    minlength: Number,
-    maxlength: Number,
-    required: {
-      type: Boolean,
-      default: true
-    },
-    autoComplete: {
-      type: String,
-      default: 'off'
-    },
-    validateEvent: {
-      type: Boolean,
-      default: true
-    }
-  },
-  data() {
-    return {
-      currentValue: this.value,
-      focus: false,
-      fillPlaceHolder: null
-    }
-  },
-  computed: {
-    computedClasses() {
-      return {
-        'material--active': this.focus,
-        'material--disabled': this.disabled,
-        'material--raised': Boolean(this.focus || this.currentValue) // has value
-      }
-    }
-  },
-  watch: {
-    value(newValue) {
-      this.currentValue = newValue
-    }
-  },
-  methods: {
-    handleModelInput(event) {
-      const value = event.target.value
-      this.$emit('input', value)
-      if (this.$parent.$options.componentName === 'ElFormItem') {
-        if (this.validateEvent) {
-          this.$parent.$emit('el.form.change', [value])
-        }
-      }
-      this.$emit('change', value)
-    },
-    handleMdFocus(event) {
-      this.focus = true
-      this.$emit('focus', event)
-      if (this.placeholder && this.placeholder !== '') {
-        this.fillPlaceHolder = this.placeholder
-      }
-    },
-    handleMdBlur(event) {
-      this.focus = false
-      this.$emit('blur', event)
-      this.fillPlaceHolder = null
-      if (this.$parent.$options.componentName === 'ElFormItem') {
-        if (this.validateEvent) {
-          this.$parent.$emit('el.form.blur', [this.currentValue])
-        }
-      }
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-  // Fonts:
-  $font-size-base: 16px;
-  $font-size-small: 18px;
-  $font-size-smallest: 12px;
-  $font-weight-normal: normal;
-  $font-weight-bold: bold;
-  $apixel: 1px;
-  // Utils
-  $spacer: 12px;
-  $transition: 0.2s ease all;
-  $index: 0px;
-  $index-has-icon: 30px;
-  // Theme:
-  $color-white: white;
-  $color-grey: #9E9E9E;
-  $color-grey-light: #E0E0E0;
-  $color-blue: #2196F3;
-  $color-red: #F44336;
-  $color-black: black;
-  // Base clases:
-  %base-bar-pseudo {
-    content: '';
-    height: 1px;
-    width: 0;
-    bottom: 0;
-    position: absolute;
-    transition: $transition;
-  }
-
-  // Mixins:
-  @mixin slided-top() {
-    top: - ($font-size-base + $spacer);
-    left: 0;
-    font-size: $font-size-base;
-    font-weight: $font-weight-bold;
-  }
-
-  // Component:
-  .material-input__component {
-    margin-top: 36px;
-    position: relative;
-    * {
-      box-sizing: border-box;
-    }
-    .iconClass {
-      .material-input__icon {
-        position: absolute;
-        left: 0;
-        line-height: $font-size-base;
-        color: $color-blue;
-        top: $spacer;
-        width: $index-has-icon;
-        height: $font-size-base;
-        font-size: $font-size-base;
-        font-weight: $font-weight-normal;
-        pointer-events: none;
-      }
-      .material-label {
-        left: $index-has-icon;
-      }
-      .material-input {
-        text-indent: $index-has-icon;
-      }
-    }
-    .material-input {
-      font-size: $font-size-base;
-      padding: $spacer $spacer $spacer - $apixel * 10 $spacer / 2;
-      display: block;
-      width: 100%;
-      border: none;
-      line-height: 1;
-      border-radius: 0;
-      &:focus {
-        outline: none;
-        border: none;
-        border-bottom: 1px solid transparent; // fixes the height issue
-      }
-    }
-    .material-label {
-      font-weight: $font-weight-normal;
-      position: absolute;
-      pointer-events: none;
-      left: $index;
-      top: 0;
-      transition: $transition;
-      font-size: $font-size-small;
-    }
-    .material-input-bar {
-      position: relative;
-      display: block;
-      width: 100%;
-      &:before {
-        @extend %base-bar-pseudo;
-        left: 50%;
-      }
-      &:after {
-        @extend %base-bar-pseudo;
-        right: 50%;
-      }
-    }
-    // Disabled state:
-    &.material--disabled {
-      .material-input {
-        border-bottom-style: dashed;
-      }
-    }
-    // Raised state:
-    &.material--raised {
-      .material-label {
-        @include slided-top();
-      }
-    }
-    // Active state:
-    &.material--active {
-      .material-input-bar {
-        &:before,
-        &:after {
-          width: 50%;
-        }
-      }
-    }
-  }
-
-  .material-input__component {
-    background: $color-white;
-    .material-input {
-      background: none;
-      color: $color-black;
-      text-indent: $index;
-      border-bottom: 1px solid $color-grey-light;
-    }
-    .material-label {
-      color: $color-grey;
-    }
-    .material-input-bar {
-      &:before,
-      &:after {
-        background: $color-blue;
-      }
-    }
-    // Active state:
-    &.material--active {
-      .material-label {
-        color: $color-blue;
-      }
-    }
-    // Errors:
-    &.material--has-errors {
-      &.material--active .material-label {
-        color: $color-red;
-      }
-      .material-input-bar {
-        &:before,
-        &:after {
-          background: transparent;
-        }
-      }
-    }
-  }
-</style>

+ 0 - 31
src/components/MarkdownEditor/default-options.js

@@ -1,31 +0,0 @@
-// doc: https://nhnent.github.io/tui.editor/api/latest/ToastUIEditor.html#ToastUIEditor
-export default {
-  minHeight: '200px',
-  previewStyle: 'vertical',
-  useCommandShortcut: true,
-  useDefaultHTMLSanitizer: true,
-  usageStatistics: false,
-  hideModeSwitch: false,
-  toolbarItems: [
-    'heading',
-    'bold',
-    'italic',
-    'strike',
-    'divider',
-    'hr',
-    'quote',
-    'divider',
-    'ul',
-    'ol',
-    'task',
-    'indent',
-    'outdent',
-    'divider',
-    'table',
-    'image',
-    'link',
-    'divider',
-    'code',
-    'codeblock'
-  ]
-}

+ 0 - 118
src/components/MarkdownEditor/index.vue

@@ -1,118 +0,0 @@
-<template>
-  <div :id="id" />
-</template>
-
-<script>
-// deps for editor
-import 'codemirror/lib/codemirror.css' // codemirror
-import 'tui-editor/dist/tui-editor.css' // editor ui
-import 'tui-editor/dist/tui-editor-contents.css' // editor content
-
-import Editor from 'tui-editor'
-import defaultOptions from './default-options'
-
-export default {
-  name: 'MarkdownEditor',
-  props: {
-    value: {
-      type: String,
-      default: ''
-    },
-    id: {
-      type: String,
-      required: false,
-      default() {
-        return 'markdown-editor-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
-      }
-    },
-    options: {
-      type: Object,
-      default() {
-        return defaultOptions
-      }
-    },
-    mode: {
-      type: String,
-      default: 'markdown'
-    },
-    height: {
-      type: String,
-      required: false,
-      default: '300px'
-    },
-    language: {
-      type: String,
-      required: false,
-      default: 'en_US' // https://github.com/nhnent/tui.editor/tree/master/src/js/langs
-    }
-  },
-  data() {
-    return {
-      editor: null
-    }
-  },
-  computed: {
-    editorOptions() {
-      const options = Object.assign({}, defaultOptions, this.options)
-      options.initialEditType = this.mode
-      options.height = this.height
-      options.language = this.language
-      return options
-    }
-  },
-  watch: {
-    value(newValue, preValue) {
-      if (newValue !== preValue && newValue !== this.editor.getValue()) {
-        this.editor.setValue(newValue)
-      }
-    },
-    language(val) {
-      this.destroyEditor()
-      this.initEditor()
-    },
-    height(newValue) {
-      this.editor.height(newValue)
-    },
-    mode(newValue) {
-      this.editor.changeMode(newValue)
-    }
-  },
-  mounted() {
-    this.initEditor()
-  },
-  destroyed() {
-    this.destroyEditor()
-  },
-  methods: {
-    initEditor() {
-      this.editor = new Editor({
-        el: document.getElementById(this.id),
-        ...this.editorOptions
-      })
-      if (this.value) {
-        this.editor.setValue(this.value)
-      }
-      this.editor.on('change', () => {
-        this.$emit('input', this.editor.getValue())
-      })
-    },
-    destroyEditor() {
-      if (!this.editor) return
-      this.editor.off('change')
-      this.editor.remove()
-    },
-    setValue(value) {
-      this.editor.setValue(value)
-    },
-    getValue() {
-      return this.editor.getValue()
-    },
-    setHtml(value) {
-      this.editor.setHtml(value)
-    },
-    getHtml() {
-      return this.editor.getHtml()
-    }
-  }
-}
-</script>

+ 0 - 101
src/components/Pagination/index.vue

@@ -1,101 +0,0 @@
-<template>
-  <div :class="{'hidden':hidden}" class="pagination-container">
-    <el-pagination
-      :background="background"
-      :current-page.sync="currentPage"
-      :page-size.sync="pageSize"
-      :layout="layout"
-      :page-sizes="pageSizes"
-      :total="total"
-      v-bind="$attrs"
-      @size-change="handleSizeChange"
-      @current-change="handleCurrentChange"
-    />
-  </div>
-</template>
-
-<script>
-import { scrollTo } from '@/utils/scroll-to'
-
-export default {
-  name: 'Pagination',
-  props: {
-    total: {
-      required: true,
-      type: Number
-    },
-    page: {
-      type: Number,
-      default: 1
-    },
-    limit: {
-      type: Number,
-      default: 20
-    },
-    pageSizes: {
-      type: Array,
-      default() {
-        return [10, 20, 30, 50]
-      }
-    },
-    layout: {
-      type: String,
-      default: 'total, sizes, prev, pager, next, jumper'
-    },
-    background: {
-      type: Boolean,
-      default: true
-    },
-    autoScroll: {
-      type: Boolean,
-      default: true
-    },
-    hidden: {
-      type: Boolean,
-      default: false
-    }
-  },
-  computed: {
-    currentPage: {
-      get() {
-        return this.page
-      },
-      set(val) {
-        this.$emit('update:page', val)
-      }
-    },
-    pageSize: {
-      get() {
-        return this.limit
-      },
-      set(val) {
-        this.$emit('update:limit', val)
-      }
-    }
-  },
-  methods: {
-    handleSizeChange(val) {
-      this.$emit('pagination', { page: this.currentPage, limit: val })
-      if (this.autoScroll) {
-        scrollTo(0, 800)
-      }
-    },
-    handleCurrentChange(val) {
-      this.$emit('pagination', { page: val, limit: this.pageSize })
-      if (this.autoScroll) {
-        scrollTo(0, 800)
-      }
-    }
-  }
-}
-</script>
-
-<style scoped>
-.pagination-container {
-  background: #fff;
-  padding: 32px 16px;
-}
-.pagination-container.hidden {
-  display: none;
-}
-</style>

+ 0 - 142
src/components/PanThumb/index.vue

@@ -1,142 +0,0 @@
-<template>
-  <div :style="{zIndex:zIndex,height:height,width:width}" class="pan-item">
-    <div class="pan-info">
-      <div class="pan-info-roles-container">
-        <slot />
-      </div>
-    </div>
-    <!-- eslint-disable-next-line -->
-    <div :style="{backgroundImage: `url(${image})`}" class="pan-thumb"></div>
-  </div>
-</template>
-
-<script>
-export default {
-  name: 'PanThumb',
-  props: {
-    image: {
-      type: String,
-      required: true
-    },
-    zIndex: {
-      type: Number,
-      default: 1
-    },
-    width: {
-      type: String,
-      default: '150px'
-    },
-    height: {
-      type: String,
-      default: '150px'
-    }
-  }
-}
-</script>
-
-<style scoped>
-.pan-item {
-  width: 200px;
-  height: 200px;
-  border-radius: 50%;
-  display: inline-block;
-  position: relative;
-  cursor: default;
-  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
-}
-
-.pan-info-roles-container {
-  padding: 20px;
-  text-align: center;
-}
-
-.pan-thumb {
-  width: 100%;
-  height: 100%;
-  background-position: center center;
-  background-size: cover;
-  border-radius: 50%;
-  overflow: hidden;
-  position: absolute;
-  transform-origin: 95% 40%;
-  transition: all 0.3s ease-in-out;
-}
-
-/* .pan-thumb:after {
-  content: '';
-  width: 8px;
-  height: 8px;
-  position: absolute;
-  border-radius: 50%;
-  top: 40%;
-  left: 95%;
-  margin: -4px 0 0 -4px;
-  background: radial-gradient(ellipse at center, rgba(14, 14, 14, 1) 0%, rgba(125, 126, 125, 1) 100%);
-  box-shadow: 0 0 1px rgba(255, 255, 255, 0.9);
-} */
-
-.pan-info {
-  position: absolute;
-  width: inherit;
-  height: inherit;
-  border-radius: 50%;
-  overflow: hidden;
-  box-shadow: inset 0 0 0 5px rgba(0, 0, 0, 0.05);
-}
-
-.pan-info h3 {
-  color: #fff;
-  text-transform: uppercase;
-  position: relative;
-  letter-spacing: 2px;
-  font-size: 18px;
-  margin: 0 60px;
-  padding: 22px 0 0 0;
-  height: 85px;
-  font-family: 'Open Sans', Arial, sans-serif;
-  text-shadow: 0 0 1px #fff, 0 1px 2px rgba(0, 0, 0, 0.3);
-}
-
-.pan-info p {
-  color: #fff;
-  padding: 10px 5px;
-  font-style: italic;
-  margin: 0 30px;
-  font-size: 12px;
-  border-top: 1px solid rgba(255, 255, 255, 0.5);
-}
-
-.pan-info p a {
-  display: block;
-  color: #333;
-  width: 80px;
-  height: 80px;
-  background: rgba(255, 255, 255, 0.3);
-  border-radius: 50%;
-  color: #fff;
-  font-style: normal;
-  font-weight: 700;
-  text-transform: uppercase;
-  font-size: 9px;
-  letter-spacing: 1px;
-  padding-top: 24px;
-  margin: 7px auto 0;
-  font-family: 'Open Sans', Arial, sans-serif;
-  opacity: 0;
-  transition: transform 0.3s ease-in-out 0.2s, opacity 0.3s ease-in-out 0.2s, background 0.2s linear 0s;
-  transform: translateX(60px) rotate(90deg);
-}
-
-.pan-info p a:hover {
-  background: rgba(255, 255, 255, 0.5);
-}
-
-.pan-item:hover .pan-thumb {
-  transform: rotate(-110deg);
-}
-
-.pan-item:hover .pan-info p a {
-  opacity: 1;
-  transform: translateX(0px) rotate(0deg);
-}
-</style>

+ 0 - 145
src/components/RightPanel/index.vue

@@ -1,145 +0,0 @@
-<template>
-  <div ref="rightPanel" :class="{show:show}" class="rightPanel-container">
-    <div class="rightPanel-background" />
-    <div class="rightPanel">
-      <div class="handle-button" :style="{'top':buttonTop+'px','background-color':theme}" @click="show=!show">
-        <i :class="show?'el-icon-close':'el-icon-setting'" />
-      </div>
-      <div class="rightPanel-items">
-        <slot />
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-import { addClass, removeClass } from '@/utils'
-
-export default {
-  name: 'RightPanel',
-  props: {
-    clickNotClose: {
-      default: false,
-      type: Boolean
-    },
-    buttonTop: {
-      default: 250,
-      type: Number
-    }
-  },
-  data() {
-    return {
-      show: false
-    }
-  },
-  computed: {
-    theme() {
-      return this.$store.state.settings.theme
-    }
-  },
-  watch: {
-    show(value) {
-      if (value && !this.clickNotClose) {
-        this.addEventClick()
-      }
-      if (value) {
-        addClass(document.body, 'showRightPanel')
-      } else {
-        removeClass(document.body, 'showRightPanel')
-      }
-    }
-  },
-  mounted() {
-    this.insertToBody()
-  },
-  beforeDestroy() {
-    const elx = this.$refs.rightPanel
-    elx.remove()
-  },
-  methods: {
-    addEventClick() {
-      window.addEventListener('click', this.closeSidebar)
-    },
-    closeSidebar(evt) {
-      const parent = evt.target.closest('.rightPanel')
-      if (!parent) {
-        this.show = false
-        window.removeEventListener('click', this.closeSidebar)
-      }
-    },
-    insertToBody() {
-      const elx = this.$refs.rightPanel
-      const body = document.querySelector('body')
-      body.insertBefore(elx, body.firstChild)
-    }
-  }
-}
-</script>
-
-<style>
-.showRightPanel {
-  overflow: hidden;
-  position: relative;
-  width: calc(100% - 15px);
-}
-</style>
-
-<style lang="scss" scoped>
-.rightPanel-background {
-  position: fixed;
-  top: 0;
-  left: 0;
-  opacity: 0;
-  transition: opacity .3s cubic-bezier(.7, .3, .1, 1);
-  background: rgba(0, 0, 0, .2);
-  z-index: -1;
-}
-
-.rightPanel {
-  width: 100%;
-  max-width: 260px;
-  height: 100vh;
-  position: fixed;
-  top: 0;
-  right: 0;
-  box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, .05);
-  transition: all .25s cubic-bezier(.7, .3, .1, 1);
-  transform: translate(100%);
-  background: #fff;
-  z-index: 40000;
-}
-
-.show {
-  transition: all .3s cubic-bezier(.7, .3, .1, 1);
-
-  .rightPanel-background {
-    z-index: 20000;
-    opacity: 1;
-    width: 100%;
-    height: 100%;
-  }
-
-  .rightPanel {
-    transform: translate(0);
-  }
-}
-
-.handle-button {
-  width: 48px;
-  height: 48px;
-  position: absolute;
-  left: -48px;
-  text-align: center;
-  font-size: 24px;
-  border-radius: 6px 0 0 6px !important;
-  z-index: 0;
-  pointer-events: auto;
-  cursor: pointer;
-  color: #fff;
-  line-height: 48px;
-  i {
-    font-size: 24px;
-    line-height: 48px;
-  }
-}
-</style>

+ 0 - 60
src/components/Screenfull/index.vue

@@ -1,60 +0,0 @@
-<template>
-  <div>
-    <svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" @click="click" />
-  </div>
-</template>
-
-<script>
-import screenfull from 'screenfull'
-
-export default {
-  name: 'Screenfull',
-  data() {
-    return {
-      isFullscreen: false
-    }
-  },
-  mounted() {
-    this.init()
-  },
-  beforeDestroy() {
-    this.destroy()
-  },
-  methods: {
-    click() {
-      if (!screenfull.enabled) {
-        this.$message({
-          message: 'you browser can not work',
-          type: 'warning'
-        })
-        return false
-      }
-      screenfull.toggle()
-    },
-    change() {
-      this.isFullscreen = screenfull.isFullscreen
-    },
-    init() {
-      if (screenfull.enabled) {
-        screenfull.on('change', this.change)
-      }
-    },
-    destroy() {
-      if (screenfull.enabled) {
-        screenfull.off('change', this.change)
-      }
-    }
-  }
-}
-</script>
-
-<style scoped>
-.screenfull-svg {
-  display: inline-block;
-  cursor: pointer;
-  fill: #5a5e66;;
-  width: 20px;
-  height: 20px;
-  vertical-align: 10px;
-}
-</style>

+ 0 - 103
src/components/Share/DropdownMenu.vue

@@ -1,103 +0,0 @@
-<template>
-  <div :class="{active:isActive}" class="share-dropdown-menu">
-    <div class="share-dropdown-menu-wrapper">
-      <span class="share-dropdown-menu-title" @click.self="clickTitle">{{ title }}</span>
-      <div v-for="(item,index) of items" :key="index" class="share-dropdown-menu-item">
-        <a v-if="item.href" :href="item.href" target="_blank">{{ item.title }}</a>
-        <span v-else>{{ item.title }}</span>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-export default {
-  props: {
-    items: {
-      type: Array,
-      default: function() {
-        return []
-      }
-    },
-    title: {
-      type: String,
-      default: 'vue'
-    }
-  },
-  data() {
-    return {
-      isActive: false
-    }
-  },
-  methods: {
-    clickTitle() {
-      this.isActive = !this.isActive
-    }
-  }
-}
-</script>
-
-<style lang="scss" >
-$n: 9; //和items.length 相同
-$t: .1s;
-.share-dropdown-menu {
-  width: 250px;
-  position: relative;
-  z-index: 1;
-  height: auto!important;
-  &-title {
-    width: 100%;
-    display: block;
-    cursor: pointer;
-    background: black;
-    color: white;
-    height: 60px;
-    line-height: 60px;
-    font-size: 20px;
-    text-align: center;
-    z-index: 2;
-    transform: translate3d(0,0,0);
-  }
-  &-wrapper {
-    position: relative;
-  }
-  &-item {
-    text-align: center;
-    position: absolute;
-    width: 100%;
-    background: #e0e0e0;
-    color: #000;
-    line-height: 60px;
-    height: 60px;
-    cursor: pointer;
-    font-size: 18px;
-    overflow: hidden;
-    opacity: 1;
-    transition: transform 0.28s ease;
-    &:hover {
-      background: black;
-      color: white;
-    }
-    @for $i from 1 through $n {
-      &:nth-of-type(#{$i}) {
-        z-index: -1;
-        transition-delay: $i*$t;
-        transform: translate3d(0, -60px, 0);
-      }
-    }
-  }
-  &.active {
-    .share-dropdown-menu-wrapper {
-      z-index: 1;
-    }
-    .share-dropdown-menu-item {
-      @for $i from 1 through $n {
-        &:nth-of-type(#{$i}) {
-          transition-delay: ($n - $i)*$t;
-          transform: translate3d(0, ($i - 1)*60px, 0);
-        }
-      }
-    }
-  }
-}
-</style>

+ 0 - 57
src/components/SizeSelect/index.vue

@@ -1,57 +0,0 @@
-<template>
-  <el-dropdown trigger="click" @command="handleSetSize">
-    <div>
-      <svg-icon class-name="size-icon" icon-class="size" />
-    </div>
-    <el-dropdown-menu slot="dropdown">
-      <el-dropdown-item v-for="item of sizeOptions" :key="item.value" :disabled="size===item.value" :command="item.value">
-        {{
-          item.label }}
-      </el-dropdown-item>
-    </el-dropdown-menu>
-  </el-dropdown>
-</template>
-
-<script>
-export default {
-  data() {
-    return {
-      sizeOptions: [
-        { label: 'Default', value: 'default' },
-        { label: 'Medium', value: 'medium' },
-        { label: 'Small', value: 'small' },
-        { label: 'Mini', value: 'mini' }
-      ]
-    }
-  },
-  computed: {
-    size() {
-      return this.$store.getters.size
-    }
-  },
-  methods: {
-    handleSetSize(size) {
-      this.$ELEMENT.size = size
-      this.$store.dispatch('app/setSize', size)
-      this.refreshView()
-      this.$message({
-        message: 'Switch Size Success',
-        type: 'success'
-      })
-    },
-    refreshView() {
-      // In order to make the cached page re-rendered
-      this.$store.dispatch('tagsView/delAllCachedViews', this.$route)
-
-      const { fullPath } = this.$route
-
-      this.$nextTick(() => {
-        this.$router.replace({
-          path: '/redirect' + fullPath
-        })
-      })
-    }
-  }
-
-}
-</script>

+ 0 - 91
src/components/Sticky/index.vue

@@ -1,91 +0,0 @@
-<template>
-  <div :style="{height:height+'px',zIndex:zIndex}">
-    <div
-      :class="className"
-      :style="{top:(isSticky ? stickyTop +'px' : ''),zIndex:zIndex,position:position,width:width,height:height+'px'}"
-    >
-      <slot>
-        <div>sticky</div>
-      </slot>
-    </div>
-  </div>
-</template>
-
-<script>
-export default {
-  name: 'Sticky',
-  props: {
-    stickyTop: {
-      type: Number,
-      default: 0
-    },
-    zIndex: {
-      type: Number,
-      default: 1
-    },
-    className: {
-      type: String,
-      default: ''
-    }
-  },
-  data() {
-    return {
-      active: false,
-      position: '',
-      width: undefined,
-      height: undefined,
-      isSticky: false
-    }
-  },
-  mounted() {
-    this.height = this.$el.getBoundingClientRect().height
-    window.addEventListener('scroll', this.handleScroll)
-    window.addEventListener('resize', this.handleResize)
-  },
-  activated() {
-    this.handleScroll()
-  },
-  destroyed() {
-    window.removeEventListener('scroll', this.handleScroll)
-    window.removeEventListener('resize', this.handleResize)
-  },
-  methods: {
-    sticky() {
-      if (this.active) {
-        return
-      }
-      this.position = 'fixed'
-      this.active = true
-      this.width = this.width + 'px'
-      this.isSticky = true
-    },
-    handleReset() {
-      if (!this.active) {
-        return
-      }
-      this.reset()
-    },
-    reset() {
-      this.position = ''
-      this.width = 'auto'
-      this.active = false
-      this.isSticky = false
-    },
-    handleScroll() {
-      const width = this.$el.getBoundingClientRect().width
-      this.width = width || 'auto'
-      const offsetTop = this.$el.getBoundingClientRect().top
-      if (offsetTop < this.stickyTop) {
-        this.sticky()
-        return
-      }
-      this.handleReset()
-    },
-    handleResize() {
-      if (this.isSticky) {
-        this.width = this.$el.getBoundingClientRect().width + 'px'
-      }
-    }
-  }
-}
-</script>

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

@@ -6,7 +6,6 @@
 </template>
 
 <script>
-// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
 import { isExternal } from '@/utils/validate'
 
 export default {

+ 0 - 113
src/components/TextHoverEffect/Mallki.vue

@@ -1,113 +0,0 @@
-<template>
-  <a :class="className" class="link--mallki" href="#">
-    {{ text }}
-    <span :data-letters="text" />
-    <span :data-letters="text" />
-  </a>
-</template>
-
-<script>
-export default {
-  props: {
-    className: {
-      type: String,
-      default: ''
-    },
-    text: {
-      type: String,
-      default: 'vue-element-admin'
-    }
-  }
-}
-</script>
-
-<style>
-/* Mallki */
-
-.link--mallki {
-  font-weight: 800;
-  color: #4dd9d5;
-  font-family: 'Dosis', sans-serif;
-  -webkit-transition: color 0.5s 0.25s;
-  transition: color 0.5s 0.25s;
-  overflow: hidden;
-  position: relative;
-  display: inline-block;
-  line-height: 1;
-  outline: none;
-  text-decoration: none;
-}
-
-.link--mallki:hover {
-  -webkit-transition: none;
-  transition: none;
-  color: transparent;
-}
-
-.link--mallki::before {
-  content: '';
-  width: 100%;
-  height: 6px;
-  margin: -3px 0 0 0;
-  background: #3888fa;
-  position: absolute;
-  left: 0;
-  top: 50%;
-  -webkit-transform: translate3d(-100%, 0, 0);
-  transform: translate3d(-100%, 0, 0);
-  -webkit-transition: -webkit-transform 0.4s;
-  transition: transform 0.4s;
-  -webkit-transition-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
-  transition-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
-}
-
-.link--mallki:hover::before {
-  -webkit-transform: translate3d(100%, 0, 0);
-  transform: translate3d(100%, 0, 0);
-}
-
-.link--mallki span {
-  position: absolute;
-  height: 50%;
-  width: 100%;
-  left: 0;
-  top: 0;
-  overflow: hidden;
-}
-
-.link--mallki span::before {
-  content: attr(data-letters);
-  color: red;
-  position: absolute;
-  left: 0;
-  width: 100%;
-  color: #3888fa;
-  -webkit-transition: -webkit-transform 0.5s;
-  transition: transform 0.5s;
-}
-
-.link--mallki span:nth-child(2) {
-  top: 50%;
-}
-
-.link--mallki span:first-child::before {
-  top: 0;
-  -webkit-transform: translate3d(0, 100%, 0);
-  transform: translate3d(0, 100%, 0);
-}
-
-.link--mallki span:nth-child(2)::before {
-  bottom: 0;
-  -webkit-transform: translate3d(0, -100%, 0);
-  transform: translate3d(0, -100%, 0);
-}
-
-.link--mallki:hover span::before {
-  -webkit-transition-delay: 0.3s;
-  transition-delay: 0.3s;
-  -webkit-transform: translate3d(0, 0, 0);
-  transform: translate3d(0, 0, 0);
-  -webkit-transition-timing-function: cubic-bezier(0.2, 1, 0.3, 1);
-  transition-timing-function: cubic-bezier(0.2, 1, 0.3, 1);
-}
-</style>

+ 0 - 111
src/components/Tinymce/components/EditorImage.vue

@@ -1,111 +0,0 @@
-<template>
-  <div class="upload-container">
-    <el-button :style="{background:color,borderColor:color}" icon="el-icon-upload" size="mini" type="primary" @click=" dialogVisible=true">
-      upload
-    </el-button>
-    <el-dialog :visible.sync="dialogVisible">
-      <el-upload
-        :multiple="true"
-        :file-list="fileList"
-        :show-file-list="true"
-        :on-remove="handleRemove"
-        :on-success="handleSuccess"
-        :before-upload="beforeUpload"
-        class="editor-slide-upload"
-        action="https://httpbin.org/post"
-        list-type="picture-card"
-      >
-        <el-button size="small" type="primary">
-          Click upload
-        </el-button>
-      </el-upload>
-      <el-button @click="dialogVisible = false">
-        Cancel
-      </el-button>
-      <el-button type="primary" @click="handleSubmit">
-        Confirm
-      </el-button>
-    </el-dialog>
-  </div>
-</template>
-
-<script>
-// import { getToken } from 'api/qiniu'
-
-export default {
-  name: 'EditorSlideUpload',
-  props: {
-    color: {
-      type: String,
-      default: '#1890ff'
-    }
-  },
-  data() {
-    return {
-      dialogVisible: false,
-      listObj: {},
-      fileList: []
-    }
-  },
-  methods: {
-    checkAllSuccess() {
-      return Object.keys(this.listObj).every(item => this.listObj[item].hasSuccess)
-    },
-    handleSubmit() {
-      const arr = Object.keys(this.listObj).map(v => this.listObj[v])
-      if (!this.checkAllSuccess()) {
-        this.$message('Please wait for all images to be uploaded successfully. If there is a network problem, please refresh the page and upload again!')
-        return
-      }
-      this.$emit('successCBK', arr)
-      this.listObj = {}
-      this.fileList = []
-      this.dialogVisible = false
-    },
-    handleSuccess(response, file) {
-      const uid = file.uid
-      const objKeyArr = Object.keys(this.listObj)
-      for (let i = 0, len = objKeyArr.length; i < len; i++) {
-        if (this.listObj[objKeyArr[i]].uid === uid) {
-          this.listObj[objKeyArr[i]].url = response.files.file
-          this.listObj[objKeyArr[i]].hasSuccess = true
-          return
-        }
-      }
-    },
-    handleRemove(file) {
-      const uid = file.uid
-      const objKeyArr = Object.keys(this.listObj)
-      for (let i = 0, len = objKeyArr.length; i < len; i++) {
-        if (this.listObj[objKeyArr[i]].uid === uid) {
-          delete this.listObj[objKeyArr[i]]
-          return
-        }
-      }
-    },
-    beforeUpload(file) {
-      const _self = this
-      const _URL = window.URL || window.webkitURL
-      const fileName = file.uid
-      this.listObj[fileName] = {}
-      return new Promise((resolve, reject) => {
-        const img = new Image()
-        img.src = _URL.createObjectURL(file)
-        img.onload = function() {
-          _self.listObj[fileName] = { hasSuccess: false, uid: file.uid, width: this.width, height: this.height }
-        }
-        resolve(true)
-      })
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.editor-slide-upload {
-  margin-bottom: 20px;
-  ::v-deep .el-upload--picture-card {
-    width: 100%;
-  }
-}
-</style>

+ 0 - 59
src/components/Tinymce/dynamicLoadScript.js

@@ -1,59 +0,0 @@
-let callbacks = []
-
-function loadedTinymce() {
-  // to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2144
-  // check is successfully downloaded script
-  return window.tinymce
-}
-
-const dynamicLoadScript = (src, callback) => {
-  const existingScript = document.getElementById(src)
-  const cb = callback || function() {}
-
-  if (!existingScript) {
-    const script = document.createElement('script')
-    script.src = src // src url for the third-party library being loaded.
-    script.id = src
-    document.body.appendChild(script)
-    callbacks.push(cb)
-    const onEnd = 'onload' in script ? stdOnEnd : ieOnEnd
-    onEnd(script)
-  }
-
-  if (existingScript && cb) {
-    if (loadedTinymce()) {
-      cb(null, existingScript)
-    } else {
-      callbacks.push(cb)
-    }
-  }
-
-  function stdOnEnd(script) {
-    script.onload = function() {
-      // this.onload = null here is necessary
-      // because even IE9 works not like others
-      this.onerror = this.onload = null
-      for (const cb of callbacks) {
-        cb(null, script)
-      }
-      callbacks = null
-    }
-    script.onerror = function() {
-      this.onerror = this.onload = null
-      cb(new Error('Failed to load ' + src), script)
-    }
-  }
-
-  function ieOnEnd(script) {
-    script.onreadystatechange = function() {
-      if (this.readyState !== 'complete' && this.readyState !== 'loaded') return
-      this.onreadystatechange = null
-      for (const cb of callbacks) {
-        cb(null, script) // there is no way to catch loading errors in IE8
-      }
-      callbacks = null
-    }
-  }
-}
-
-export default dynamicLoadScript

+ 0 - 247
src/components/Tinymce/index.vue

@@ -1,247 +0,0 @@
-<template>
-  <div :class="{fullscreen:fullscreen}" class="tinymce-container" :style="{width:containerWidth}">
-    <textarea :id="tinymceId" class="tinymce-textarea" />
-    <div class="editor-custom-btn-container">
-      <editorImage color="#1890ff" class="editor-upload-btn" @successCBK="imageSuccessCBK" />
-    </div>
-  </div>
-</template>
-
-<script>
-/**
- * docs:
- * https://panjiachen.github.io/vue-element-admin-site/feature/component/rich-editor.html#tinymce
- */
-import editorImage from './components/EditorImage'
-import plugins from './plugins'
-import toolbar from './toolbar'
-import load from './dynamicLoadScript'
-
-// why use this cdn, detail see https://github.com/PanJiaChen/tinymce-all-in-one
-const tinymceCDN = 'https://cdn.jsdelivr.net/npm/tinymce-all-in-one@4.9.3/tinymce.min.js'
-
-export default {
-  name: 'Tinymce',
-  components: { editorImage },
-  props: {
-    id: {
-      type: String,
-      default: function() {
-        return 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
-      }
-    },
-    value: {
-      type: String,
-      default: ''
-    },
-    toolbar: {
-      type: Array,
-      required: false,
-      default() {
-        return []
-      }
-    },
-    menubar: {
-      type: String,
-      default: 'file edit insert view format table'
-    },
-    height: {
-      type: [Number, String],
-      required: false,
-      default: 360
-    },
-    width: {
-      type: [Number, String],
-      required: false,
-      default: 'auto'
-    }
-  },
-  data() {
-    return {
-      hasChange: false,
-      hasInit: false,
-      tinymceId: this.id,
-      fullscreen: false,
-      languageTypeList: {
-        'en': 'en',
-        'zh': 'zh_CN',
-        'es': 'es_MX',
-        'ja': 'ja'
-      }
-    }
-  },
-  computed: {
-    containerWidth() {
-      const width = this.width
-      if (/^[\d]+(\.[\d]+)?$/.test(width)) { // matches `100`, `'100'`
-        return `${width}px`
-      }
-      return width
-    }
-  },
-  watch: {
-    value(val) {
-      if (!this.hasChange && this.hasInit) {
-        this.$nextTick(() =>
-          window.tinymce.get(this.tinymceId).setContent(val || ''))
-      }
-    }
-  },
-  mounted() {
-    this.init()
-  },
-  activated() {
-    if (window.tinymce) {
-      this.initTinymce()
-    }
-  },
-  deactivated() {
-    this.destroyTinymce()
-  },
-  destroyed() {
-    this.destroyTinymce()
-  },
-  methods: {
-    init() {
-      // dynamic load tinymce from cdn
-      load(tinymceCDN, (err) => {
-        if (err) {
-          this.$message.error(err.message)
-          return
-        }
-        this.initTinymce()
-      })
-    },
-    initTinymce() {
-      const _this = this
-      window.tinymce.init({
-        selector: `#${this.tinymceId}`,
-        language: this.languageTypeList['en'],
-        height: this.height,
-        body_class: 'panel-body ',
-        object_resizing: false,
-        toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
-        menubar: this.menubar,
-        plugins: plugins,
-        end_container_on_empty_block: true,
-        powerpaste_word_import: 'clean',
-        code_dialog_height: 450,
-        code_dialog_width: 1000,
-        advlist_bullet_styles: 'square',
-        advlist_number_styles: 'default',
-        imagetools_cors_hosts: ['www.tinymce.com', 'codepen.io'],
-        default_link_target: '_blank',
-        link_title: false,
-        nonbreaking_force_tab: true, // inserting nonbreaking space &nbsp; need Nonbreaking Space Plugin
-        init_instance_callback: editor => {
-          if (_this.value) {
-            editor.setContent(_this.value)
-          }
-          _this.hasInit = true
-          editor.on('NodeChange Change KeyUp SetContent', () => {
-            this.hasChange = true
-            this.$emit('input', editor.getContent())
-          })
-        },
-        setup(editor) {
-          editor.on('FullscreenStateChanged', (e) => {
-            _this.fullscreen = e.state
-          })
-        },
-        // it will try to keep these URLs intact
-        // https://www.tiny.cloud/docs-3x/reference/configuration/Configuration3x@convert_urls/
-        // https://stackoverflow.com/questions/5196205/disable-tinymce-absolute-to-relative-url-conversions
-        convert_urls: false
-        // 整合七牛上传
-        // images_dataimg_filter(img) {
-        //   setTimeout(() => {
-        //     const $image = $(img);
-        //     $image.removeAttr('width');
-        //     $image.removeAttr('height');
-        //     if ($image[0].height && $image[0].width) {
-        //       $image.attr('data-wscntype', 'image');
-        //       $image.attr('data-wscnh', $image[0].height);
-        //       $image.attr('data-wscnw', $image[0].width);
-        //       $image.addClass('wscnph');
-        //     }
-        //   }, 0);
-        //   return img
-        // },
-        // images_upload_handler(blobInfo, success, failure, progress) {
-        //   progress(0);
-        //   const token = _this.$store.getters.token;
-        //   getToken(token).then(response => {
-        //     const url = response.data.qiniu_url;
-        //     const formData = new FormData();
-        //     formData.append('token', response.data.qiniu_token);
-        //     formData.append('key', response.data.qiniu_key);
-        //     formData.append('file', blobInfo.blob(), url);
-        //     upload(formData).then(() => {
-        //       success(url);
-        //       progress(100);
-        //     })
-        //   }).catch(err => {
-        //     failure('出现未知问题,刷新页面,或者联系程序员')
-        //     console.log(err);
-        //   });
-        // },
-      })
-    },
-    destroyTinymce() {
-      const tinymce = window.tinymce.get(this.tinymceId)
-      if (this.fullscreen) {
-        tinymce.execCommand('mceFullScreen')
-      }
-
-      if (tinymce) {
-        tinymce.destroy()
-      }
-    },
-    setContent(value) {
-      window.tinymce.get(this.tinymceId).setContent(value)
-    },
-    getContent() {
-      window.tinymce.get(this.tinymceId).getContent()
-    },
-    imageSuccessCBK(arr) {
-      arr.forEach(v => window.tinymce.get(this.tinymceId).insertContent(`<img class="wscnph" src="${v.url}" >`))
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.tinymce-container {
-  position: relative;
-  line-height: normal;
-}
-
-.tinymce-container {
-  ::v-deep {
-    .mce-fullscreen {
-      z-index: 10000;
-    }
-  }
-}
-
-.tinymce-textarea {
-  visibility: hidden;
-  z-index: -1;
-}
-
-.editor-custom-btn-container {
-  position: absolute;
-  right: 4px;
-  top: 4px;
-  /*z-index: 2005;*/
-}
-
-.fullscreen .editor-custom-btn-container {
-  z-index: 10000;
-  position: fixed;
-}
-
-.editor-upload-btn {
-  display: inline-block;
-}
-</style>

+ 0 - 7
src/components/Tinymce/plugins.js

@@ -1,7 +0,0 @@
-// Any plugins you want to use has to be imported
-// Detail plugins list see https://www.tinymce.com/docs/plugins/
-// Custom builds see https://www.tinymce.com/download/custom-builds/
-
-const plugins = ['advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount']
-
-export default plugins

+ 0 - 6
src/components/Tinymce/toolbar.js

@@ -1,6 +0,0 @@
-// Here is a list of the toolbar
-// Detail list see https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols
-
-const toolbar = ['searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent  blockquote undo redo removeformat subscript superscript code codesample', 'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen']
-
-export default toolbar

+ 0 - 134
src/components/Upload/SingleImage.vue

@@ -1,134 +0,0 @@
-<template>
-  <div class="upload-container">
-    <el-upload
-      :data="dataObj"
-      :multiple="false"
-      :show-file-list="false"
-      :on-success="handleImageSuccess"
-      class="image-uploader"
-      drag
-      action="https://httpbin.org/post"
-    >
-      <i class="el-icon-upload" />
-      <div class="el-upload__text">
-        将文件拖到此处,或<em>点击上传</em>
-      </div>
-    </el-upload>
-    <div class="image-preview">
-      <div v-show="imageUrl.length>1" class="image-preview-wrapper">
-        <img :src="imageUrl+'?imageView2/1/w/200/h/200'">
-        <div class="image-preview-action">
-          <i class="el-icon-delete" @click="rmImage" />
-        </div>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-import { getToken } from '@/api/qiniu'
-
-export default {
-  name: 'SingleImageUpload',
-  props: {
-    value: {
-      type: String,
-      default: ''
-    }
-  },
-  data() {
-    return {
-      tempUrl: '',
-      dataObj: { token: '', key: '' }
-    }
-  },
-  computed: {
-    imageUrl() {
-      return this.value
-    }
-  },
-  methods: {
-    rmImage() {
-      this.emitInput('')
-    },
-    emitInput(val) {
-      this.$emit('input', val)
-    },
-    handleImageSuccess() {
-      this.emitInput(this.tempUrl)
-    },
-    beforeUpload() {
-      const _self = this
-      return new Promise((resolve, reject) => {
-        getToken().then(response => {
-          const key = response.data.qiniu_key
-          const token = response.data.qiniu_token
-          _self._data.dataObj.token = token
-          _self._data.dataObj.key = key
-          this.tempUrl = response.data.qiniu_url
-          resolve(true)
-        }).catch(err => {
-          console.log(err)
-          reject(false)
-        })
-      })
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-    @import "~@/styles/mixin.scss";
-    .upload-container {
-        width: 100%;
-        position: relative;
-        @include clearfix;
-        .image-uploader {
-            width: 60%;
-            float: left;
-        }
-        .image-preview {
-            width: 200px;
-            height: 200px;
-            position: relative;
-            border: 1px dashed #d9d9d9;
-            float: left;
-            margin-left: 50px;
-            .image-preview-wrapper {
-                position: relative;
-                width: 100%;
-                height: 100%;
-                img {
-                    width: 100%;
-                    height: 100%;
-                }
-            }
-            .image-preview-action {
-                position: absolute;
-                width: 100%;
-                height: 100%;
-                left: 0;
-                top: 0;
-                cursor: default;
-                text-align: center;
-                color: #fff;
-                opacity: 0;
-                font-size: 20px;
-                background-color: rgba(0, 0, 0, .5);
-                transition: opacity .3s;
-                cursor: pointer;
-                text-align: center;
-                line-height: 200px;
-                .el-icon-delete {
-                    font-size: 36px;
-                }
-            }
-            &:hover {
-                .image-preview-action {
-                    opacity: 1;
-                }
-            }
-        }
-    }
-
-</style>

+ 0 - 130
src/components/Upload/SingleImage2.vue

@@ -1,130 +0,0 @@
-<template>
-  <div class="singleImageUpload2 upload-container">
-    <el-upload
-      :data="dataObj"
-      :multiple="false"
-      :show-file-list="false"
-      :on-success="handleImageSuccess"
-      class="image-uploader"
-      drag
-      action="https://httpbin.org/post"
-    >
-      <i class="el-icon-upload" />
-      <div class="el-upload__text">
-        Drag或<em>点击上传</em>
-      </div>
-    </el-upload>
-    <div v-show="imageUrl.length>0" class="image-preview">
-      <div v-show="imageUrl.length>1" class="image-preview-wrapper">
-        <img :src="imageUrl">
-        <div class="image-preview-action">
-          <i class="el-icon-delete" @click="rmImage" />
-        </div>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-import { getToken } from '@/api/qiniu'
-
-export default {
-  name: 'SingleImageUpload2',
-  props: {
-    value: {
-      type: String,
-      default: ''
-    }
-  },
-  data() {
-    return {
-      tempUrl: '',
-      dataObj: { token: '', key: '' }
-    }
-  },
-  computed: {
-    imageUrl() {
-      return this.value
-    }
-  },
-  methods: {
-    rmImage() {
-      this.emitInput('')
-    },
-    emitInput(val) {
-      this.$emit('input', val)
-    },
-    handleImageSuccess() {
-      this.emitInput(this.tempUrl)
-    },
-    beforeUpload() {
-      const _self = this
-      return new Promise((resolve, reject) => {
-        getToken().then(response => {
-          const key = response.data.qiniu_key
-          const token = response.data.qiniu_token
-          _self._data.dataObj.token = token
-          _self._data.dataObj.key = key
-          this.tempUrl = response.data.qiniu_url
-          resolve(true)
-        }).catch(() => {
-          reject(false)
-        })
-      })
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.upload-container {
-  width: 100%;
-  height: 100%;
-  position: relative;
-  .image-uploader {
-    height: 100%;
-  }
-  .image-preview {
-    width: 100%;
-    height: 100%;
-    position: absolute;
-    left: 0px;
-    top: 0px;
-    border: 1px dashed #d9d9d9;
-    .image-preview-wrapper {
-      position: relative;
-      width: 100%;
-      height: 100%;
-      img {
-        width: 100%;
-        height: 100%;
-      }
-    }
-    .image-preview-action {
-      position: absolute;
-      width: 100%;
-      height: 100%;
-      left: 0;
-      top: 0;
-      cursor: default;
-      text-align: center;
-      color: #fff;
-      opacity: 0;
-      font-size: 20px;
-      background-color: rgba(0, 0, 0, .5);
-      transition: opacity .3s;
-      cursor: pointer;
-      text-align: center;
-      line-height: 200px;
-      .el-icon-delete {
-        font-size: 36px;
-      }
-    }
-    &:hover {
-      .image-preview-action {
-        opacity: 1;
-      }
-    }
-  }
-}
-</style>

+ 0 - 157
src/components/Upload/SingleImage3.vue

@@ -1,157 +0,0 @@
-<template>
-  <div class="upload-container">
-    <el-upload
-      :data="dataObj"
-      :multiple="false"
-      :show-file-list="false"
-      :on-success="handleImageSuccess"
-      class="image-uploader"
-      drag
-      action="https://httpbin.org/post"
-    >
-      <i class="el-icon-upload" />
-      <div class="el-upload__text">
-        将文件拖到此处,或<em>点击上传</em>
-      </div>
-    </el-upload>
-    <div class="image-preview image-app-preview">
-      <div v-show="imageUrl.length>1" class="image-preview-wrapper">
-        <img :src="imageUrl">
-        <div class="image-preview-action">
-          <i class="el-icon-delete" @click="rmImage" />
-        </div>
-      </div>
-    </div>
-    <div class="image-preview">
-      <div v-show="imageUrl.length>1" class="image-preview-wrapper">
-        <img :src="imageUrl">
-        <div class="image-preview-action">
-          <i class="el-icon-delete" @click="rmImage" />
-        </div>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-import { getToken } from '@/api/qiniu'
-
-export default {
-  name: 'SingleImageUpload3',
-  props: {
-    value: {
-      type: String,
-      default: ''
-    }
-  },
-  data() {
-    return {
-      tempUrl: '',
-      dataObj: { token: '', key: '' }
-    }
-  },
-  computed: {
-    imageUrl() {
-      return this.value
-    }
-  },
-  methods: {
-    rmImage() {
-      this.emitInput('')
-    },
-    emitInput(val) {
-      this.$emit('input', val)
-    },
-    handleImageSuccess(file) {
-      this.emitInput(file.files.file)
-    },
-    beforeUpload() {
-      const _self = this
-      return new Promise((resolve, reject) => {
-        getToken().then(response => {
-          const key = response.data.qiniu_key
-          const token = response.data.qiniu_token
-          _self._data.dataObj.token = token
-          _self._data.dataObj.key = key
-          this.tempUrl = response.data.qiniu_url
-          resolve(true)
-        }).catch(err => {
-          console.log(err)
-          reject(false)
-        })
-      })
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-@import "~@/styles/mixin.scss";
-.upload-container {
-  width: 100%;
-  position: relative;
-  @include clearfix;
-  .image-uploader {
-    width: 35%;
-    float: left;
-  }
-  .image-preview {
-    width: 200px;
-    height: 200px;
-    position: relative;
-    border: 1px dashed #d9d9d9;
-    float: left;
-    margin-left: 50px;
-    .image-preview-wrapper {
-      position: relative;
-      width: 100%;
-      height: 100%;
-      img {
-        width: 100%;
-        height: 100%;
-      }
-    }
-    .image-preview-action {
-      position: absolute;
-      width: 100%;
-      height: 100%;
-      left: 0;
-      top: 0;
-      cursor: default;
-      text-align: center;
-      color: #fff;
-      opacity: 0;
-      font-size: 20px;
-      background-color: rgba(0, 0, 0, .5);
-      transition: opacity .3s;
-      cursor: pointer;
-      text-align: center;
-      line-height: 200px;
-      .el-icon-delete {
-        font-size: 36px;
-      }
-    }
-    &:hover {
-      .image-preview-action {
-        opacity: 1;
-      }
-    }
-  }
-  .image-app-preview {
-    width: 320px;
-    height: 180px;
-    position: relative;
-    border: 1px dashed #d9d9d9;
-    float: left;
-    margin-left: 50px;
-    .app-fake-conver {
-      height: 44px;
-      position: absolute;
-      width: 100%; // background: rgba(0, 0, 0, .1);
-      text-align: center;
-      line-height: 64px;
-      color: #fff;
-    }
-  }
-}
-</style>

+ 0 - 138
src/components/UploadExcel/index.vue

@@ -1,138 +0,0 @@
-<template>
-  <div>
-    <input ref="excel-upload-input" class="excel-upload-input" type="file" accept=".xlsx, .xls" @change="handleClick">
-    <div class="drop" @drop="handleDrop" @dragover="handleDragover" @dragenter="handleDragover">
-      Drop excel file here or
-      <el-button :loading="loading" style="margin-left:16px;" size="mini" type="primary" @click="handleUpload">
-        Browse
-      </el-button>
-    </div>
-  </div>
-</template>
-
-<script>
-import XLSX from 'xlsx'
-
-export default {
-  props: {
-    beforeUpload: Function, // eslint-disable-line
-    onSuccess: Function// eslint-disable-line
-  },
-  data() {
-    return {
-      loading: false,
-      excelData: {
-        header: null,
-        results: null
-      }
-    }
-  },
-  methods: {
-    generateData({ header, results }) {
-      this.excelData.header = header
-      this.excelData.results = results
-      this.onSuccess && this.onSuccess(this.excelData)
-    },
-    handleDrop(e) {
-      e.stopPropagation()
-      e.preventDefault()
-      if (this.loading) return
-      const files = e.dataTransfer.files
-      if (files.length !== 1) {
-        this.$message.error('Only support uploading one file!')
-        return
-      }
-      const rawFile = files[0] // only use files[0]
-
-      if (!this.isExcel(rawFile)) {
-        this.$message.error('Only supports upload .xlsx, .xls, .csv suffix files')
-        return false
-      }
-      this.upload(rawFile)
-      e.stopPropagation()
-      e.preventDefault()
-    },
-    handleDragover(e) {
-      e.stopPropagation()
-      e.preventDefault()
-      e.dataTransfer.dropEffect = 'copy'
-    },
-    handleUpload() {
-      this.$refs['excel-upload-input'].click()
-    },
-    handleClick(e) {
-      const files = e.target.files
-      const rawFile = files[0] // only use files[0]
-      if (!rawFile) return
-      this.upload(rawFile)
-    },
-    upload(rawFile) {
-      this.$refs['excel-upload-input'].value = null // fix can't select the same excel
-
-      if (!this.beforeUpload) {
-        this.readerData(rawFile)
-        return
-      }
-      const before = this.beforeUpload(rawFile)
-      if (before) {
-        this.readerData(rawFile)
-      }
-    },
-    readerData(rawFile) {
-      this.loading = true
-      return new Promise((resolve, reject) => {
-        const reader = new FileReader()
-        reader.onload = e => {
-          const data = e.target.result
-          const workbook = XLSX.read(data, { type: 'array' })
-          const firstSheetName = workbook.SheetNames[0]
-          const worksheet = workbook.Sheets[firstSheetName]
-          const header = this.getHeaderRow(worksheet)
-          const results = XLSX.utils.sheet_to_json(worksheet)
-          this.generateData({ header, results })
-          this.loading = false
-          resolve()
-        }
-        reader.readAsArrayBuffer(rawFile)
-      })
-    },
-    getHeaderRow(sheet) {
-      const headers = []
-      const range = XLSX.utils.decode_range(sheet['!ref'])
-      let C
-      const R = range.s.r
-      /* start in the first row */
-      for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */
-        const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]
-        /* find the cell in the first row */
-        let hdr = 'UNKNOWN ' + C // <-- replace with your desired default
-        if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
-        headers.push(hdr)
-      }
-      return headers
-    },
-    isExcel(file) {
-      return /\.(xlsx|xls|csv)$/.test(file.name)
-    }
-  }
-}
-</script>
-
-<style scoped>
-.excel-upload-input{
-  display: none;
-  z-index: -9999;
-}
-.drop{
-  border: 2px dashed #bbb;
-  width: 600px;
-  height: 160px;
-  line-height: 160px;
-  margin: 0 auto;
-  font-size: 24px;
-  border-radius: 5px;
-  text-align: center;
-  color: #bbb;
-  position: relative;
-}
-</style>

+ 1 - 2
src/filters/index.js

@@ -1,4 +1,3 @@
-// import parseTime, formatTime and set to filter
 export { parseTime, formatTime } from '@/utils'
 
 /**
@@ -69,4 +68,4 @@ export function uppercaseFirst(string) {
 export function numFilter(value) {
   const realVal = parseFloat(value).toFixed(2)
   return realVal
-}
+}

+ 0 - 1
src/utils/request.js

@@ -50,7 +50,6 @@ service.interceptors.response.use(
    */
   response => {
     const res = response.data
-    // if the custom code is not 20000, it is judged as an error.
     if (res.code !== 0) {
       Message({
         message: res.msg || 'Error',

+ 20 - 20
src/views/equipment-monitoring/components/SubTitle.vue

@@ -12,7 +12,7 @@
         <div class="store-list active" @click="changePower">开始换电</div>
         <div class="store-list" @click="FireControlStoreHouse">消防换仓</div>
         <div class="store-list" @click="CheckStoreHouse">检修换仓</div>
-        <div class="store-list" @click="resetMachine">机器人复位</div>
+        <!-- <div class="store-list" @click="resetMachine">机器人复位</div> -->
       </div>
     </div>
     <div class="rolemanage">
@@ -118,29 +118,29 @@ export default {
       })
         .then(async() => {
           const res = await beginSwap()
-          // this.$message({
-          //   type: 'success',
-          //   message: '操作成功!'
-          // })
-        })
-        .catch(err => { console.error(err) })
-    },
-    // 机器人复位
-    resetMachine() {
-      this.$confirm('请确认机器人复位?', '机器人复位', {
-        confirmButtonText: '确认',
-        cancelButtonText: '取消',
-        type: 'warning'
-      })
-        .then(async() => {
-          const res = await resetRobot()
           this.$message({
             type: 'success',
-            message: '操作成功!'
+            message: res.data,
           })
         })
         .catch(err => { console.error(err) })
     },
+    // 机器人复位
+    // resetMachine() {
+    //   this.$confirm('请确认机器人复位?', '机器人复位', {
+    //     confirmButtonText: '确认',
+    //     cancelButtonText: '取消',
+    //     type: 'warning'
+    //   })
+    //     .then(async() => {
+    //       const res = await resetRobot()
+    //       this.$message({
+    //         type: 'success',
+    //         message: res.data,
+    //       })
+    //     })
+    //     .catch(err => { console.error(err) })
+    // },
     // 检修消防换仓,显示弹窗
     CheckStoreHouse() {
       this.dialogType = 'check'
@@ -164,7 +164,7 @@ export default {
                 this.dialogStoreVisible = false
                 this.$message({
                   type: 'success',
-                  message: '操作成功!'
+                  message: res.data,
                 })
                 this.resetForm()
               } else {
@@ -182,7 +182,7 @@ export default {
                 this.dialogStoreVisible = false
                 this.$message({
                   type: 'success',
-                  message: '操作成功!'
+                  message: res.data,
                 })
                 this.resetForm()
               } else {

+ 1 - 4
src/views/error-page/404.vue

@@ -9,12 +9,9 @@
       </div>
       <div class="bullshit">
         <div class="bullshit__oops">OOPS!</div>
-        <div class="bullshit__info">All rights reserved
-          <a style="color:#20a0ff" href="https://wallstreetcn.com" target="_blank">wallstreetcn</a>
-        </div>
         <div class="bullshit__headline">{{ message }}</div>
         <div class="bullshit__info">Please check that the URL you entered is correct, or click the button below to return to the homepage.</div>
-        <a href="" class="bullshit__return-home">Back to home</a>
+        <a href="/#/login" class="bullshit__return-home">Back to home</a>
       </div>
     </div>
   </div>

+ 12 - 13
src/views/permission/role.vue

@@ -26,8 +26,8 @@
         <el-button type="primary" class="addbtn" @click="handleAddRole">新增账号</el-button>
       </div>
       <div class="charge-table-bottom">
-        <el-table
-          :data="UserList"
+        <el-table
+          :data="UserList"
           :header-cell-style="{
             background: '#1d283e',
             borderColor: '#2f3c86',
@@ -37,7 +37,7 @@
             fontSize: '16px',
           }"
           stripe
-          style="width: 100%"
+          style="width: 100%"
           :default-sort="{prop: 'date', order: 'descending'}"
         >
           <el-table-column label="序号" type="index" :index="indexMethod" width="300" />
@@ -63,14 +63,14 @@
       </div>
 
       <div class="pageblock">
-        <el-pagination
-          :current-page="queryParams.page"
+        <el-pagination
+          :current-page="queryParams.page"
           :page-sizes="[10, 20, 30, 40]"
-          :page-size="queryParams.pageSize"
-          layout="total, sizes, prev, pager, next, jumper"
+          :page-size="queryParams.pageSize"
+          layout="total, sizes, prev, pager, next, jumper"
           :total="total"
-          @size-change="handleSizeChange"
-          @current-change="handleCurrentChange"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
         />
       </div>
     </div>
@@ -205,7 +205,7 @@ export default {
                 return this.$message.error(res.msg)
               }
             })
-          }
+          }
         }
       })
     },
@@ -239,7 +239,7 @@ export default {
       this.formData.remark = row.remark
       this.formData.id = row.id
       this.dialogType = 'edit'
-      this.dialogUserVisible = true
+      this.dialogUserVisible = true
     },
     handleDelete(userId) {
       this.$confirm('删除数据将丢失,请确认是否删除', '确认删除', {
@@ -249,7 +249,6 @@ export default {
       })
         .then(async() => {
           await deleteUser({ id: userId })
-
           this.$message({
             type: 'success',
             message: '删除成功!'
@@ -328,4 +327,4 @@ export default {
       color: white;
   }
 }
-</style>
+</style>

+ 9 - 1
src/views/power-change-monitoring/index.vue

@@ -206,7 +206,7 @@
             :key="item.id"
             class="recordinfo"
           >
-            <span>{{ item.code }}</span><span>{{ item.equipment }}</span><span>{{ item.info }}</span><span>{{ item.beginTime }}</span>
+            <span>{{ item.code }}</span><span>{{ item.equipment }}</span><span :title="item.info">{{ item.info }}</span><span>{{ item.beginTime }}</span>
           </div>
         </div>
       </div>
@@ -748,6 +748,10 @@ export default {
           width: 190px;
           text-align: left;
           text-indent: 15px;
+          overflow: hidden; 
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          cursor: pointer;
         }
         span:last-child {
           flex: 1;
@@ -772,6 +776,10 @@ export default {
           width: 190px;
           text-align: left;
           text-indent: 15px;
+          overflow: hidden; 
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          cursor: pointer;
         }
         span:last-child {
           flex: 1;

+ 6 - 9
vue.config.js

@@ -41,8 +41,6 @@ module.exports = {
     },
   },
   configureWebpack: {
-    // provide the app's title in webpack's name field, so that
-    // it can be accessed in index.html to inject the correct title.
     name: name,
     resolve: {
       alias: {
@@ -83,7 +81,6 @@ module.exports = {
             .plugin('ScriptExtHtmlWebpackPlugin')
             .after('html')
             .use('script-ext-html-webpack-plugin', [{
-              // `runtime` must same as runtimeChunk name. default is `runtime`
               inline: /runtime\..*\.js$/
             }])
             .end()
@@ -95,17 +92,17 @@ module.exports = {
                   name: 'chunk-libs',
                   test: /[\\/]node_modules[\\/]/,
                   priority: 10,
-                  chunks: 'initial' // only package third parties that are initially dependent
+                  chunks: 'initial' 
                 },
                 elementUI: {
-                  name: 'chunk-elementUI', // split elementUI into a single package
-                  priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
-                  test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
+                  name: 'chunk-elementUI', 
+                  priority: 20, 
+                  test: /[\\/]node_modules[\\/]_?element-ui(.*)/ 
                 },
                 commons: {
                   name: 'chunk-commons',
-                  test: resolve('src/components'), // can customize your rules
-                  minChunks: 3, //  minimum common number
+                  test: resolve('src/components'), 
+                  minChunks: 3, 
                   priority: 5,
                   reuseExistingChunk: true
                 }