Pārlūkot izejas kodu

Merge branch 'developer' into developerA

yuwenjun1997 2 gadi atpakaļ
vecāks
revīzija
dead7d123d
86 mainītis faili ar 3320 papildinājumiem un 1921 dzēšanām
  1. 5 6
      public/index.html
  2. 40 0
      src/api/system.js
  3. BIN
      src/assets/img/drag-auth-temp.jpg
  4. BIN
      src/assets/img/drag-qrcode-temp.png
  5. 53 0
      src/components/AuditButtonGroup/index.vue
  6. 30 0
      src/components/AuditStatus/index.vue
  7. 89 0
      src/components/DragLayout/dragmove.js
  8. 193 0
      src/components/DragLayout/index.vue
  9. 12 13
      src/components/IconList/index.vue
  10. 1 1
      src/components/Pagination/index.vue
  11. 44 0
      src/components/SimpleAMap/common/utils.js
  12. 157 0
      src/components/SimpleAMap/index.vue
  13. 13 0
      src/components/index.js
  14. 34 22
      src/components/qrcode/index.vue
  15. 6 3
      src/main.js
  16. 0 5
      src/permission.js
  17. 2 0
      src/router/index.js
  18. 7 35
      src/router/module/admin/settings.js
  19. 63 0
      src/router/module/normal/settings.js
  20. 0 104
      src/router/router-map.js
  21. 0 692
      src/styles/index.css
  22. 0 0
      src/styles/index.min.css
  23. 9 5
      src/styles/index.scss
  24. 0 0
      src/utils/format-routes-to-modules.js
  25. 0 75
      src/utils/formatRoutesToModule.js
  26. 15 0
      src/utils/index.js
  27. 0 3
      src/utils/open-window.js
  28. 1 15
      src/views/admin/audit/club/device/index.vue
  29. 4 6
      src/views/admin/audit/club/index.vue
  30. 27 26
      src/views/admin/audit/club/list.vue
  31. 20 4
      src/views/admin/audit/club/review.vue
  32. 3 5
      src/views/admin/audit/device/index.vue
  33. 7 35
      src/views/admin/audit/device/list.vue
  34. 8 19
      src/views/admin/audit/material/article/index.vue
  35. 2 22
      src/views/admin/audit/material/file/index.vue
  36. 1 16
      src/views/admin/audit/material/image/index.vue
  37. 13 35
      src/views/admin/audit/material/index.vue
  38. 2 22
      src/views/admin/audit/material/package/index.vue
  39. 1 16
      src/views/admin/audit/material/video/index.vue
  40. 10 19
      src/views/admin/audit/personnel/index.vue
  41. 1 14
      src/views/admin/audit/personnel/operate/index.vue
  42. 1 14
      src/views/admin/audit/personnel/training/index.vue
  43. 27 4
      src/views/admin/logistics-licensed/club/detail.vue
  44. 5 16
      src/views/admin/logistics-licensed/club/device/index.vue
  45. 0 1
      src/views/admin/logistics-licensed/components/club-list.vue
  46. 0 1
      src/views/admin/logistics-licensed/components/supplier-list.vue
  47. 0 1
      src/views/admin/member/index.vue
  48. 167 0
      src/views/admin/settings/auth-card/components/supplier-list.vue
  49. 346 0
      src/views/admin/settings/auth-card/index.vue
  50. 0 36
      src/views/admin/settings/menus/children-list.vue
  51. 385 0
      src/views/admin/settings/menus/components/edit-page.vue
  52. 232 163
      src/views/admin/settings/menus/components/table-list.vue
  53. 0 277
      src/views/admin/settings/menus/edit.vue
  54. 0 1
      src/views/admin/settings/menus/index.vue
  55. 1 14
      src/views/admin/supplier/club/device/index.vue
  56. 1 14
      src/views/admin/supplier/club/index.vue
  57. 40 24
      src/views/admin/supplier/edit.vue
  58. 2 19
      src/views/admin/supplier/index.vue
  59. 0 4
      src/views/common/helper/document/index.vue
  60. 0 4
      src/views/common/helper/video/index.vue
  61. 2 20
      src/views/normal/audit/club/components/club-list.vue
  62. 1 15
      src/views/normal/audit/club/components/device-list.vue
  63. 20 4
      src/views/normal/audit/club/review.vue
  64. 0 1
      src/views/normal/club/device-cate.vue
  65. 29 1
      src/views/normal/club/device/edit.vue
  66. 0 1
      src/views/normal/club/device/index.vue
  67. 210 14
      src/views/normal/club/edit.vue
  68. 0 1
      src/views/normal/club/index.vue
  69. 3 3
      src/views/normal/club/user/index-temp.vue
  70. 0 1
      src/views/normal/club/user/index.vue
  71. 1 3
      src/views/normal/feedback/index.vue
  72. 2 3
      src/views/normal/material/article/index.vue
  73. 5 6
      src/views/normal/material/file/index.vue
  74. 2 2
      src/views/normal/material/image/edit.vue
  75. 0 1
      src/views/normal/material/image/index.vue
  76. 4 5
      src/views/normal/material/package/index.vue
  77. 54 26
      src/views/normal/material/video/index.vue
  78. 0 1
      src/views/normal/personnel/operate/index.vue
  79. 0 1
      src/views/normal/personnel/training/index.vue
  80. 170 0
      src/views/normal/settings/accounts/edit.vue
  81. 118 0
      src/views/normal/settings/accounts/index.vue
  82. 142 0
      src/views/normal/settings/auth-card/components/supplier-list.vue
  83. 227 0
      src/views/normal/settings/auth-card/index.vue
  84. 143 0
      src/views/normal/settings/roles/edit.vue
  85. 107 0
      src/views/normal/settings/roles/index.vue
  86. 0 1
      src/views/normal/user/index.vue

+ 5 - 6
public/index.html

@@ -7,16 +7,15 @@
     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
     <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
     <title><%= webpackConfig.name %></title>
-    <script
-      type="text/javascript"
-      src="//api.map.baidu.com/api?type=webgl&v=1.0&ak=vsIfSztpPmCtmBRfRiIAM57hbxBQbmgQ"
-    ></script>
     <script type="text/javascript">
       window._AMapSecurityConfig = {
-        securityJsCode: '0eff43c06afaa04ad39df64276c2e375'
+        securityJsCode: 'ff3114e0be935539f0ca5c9a80406752'
       }
     </script>
-    <script src="https://webapi.amap.com/loader.js"></script>
+    <script
+      type="text/javascript"
+      src="https://webapi.amap.com/maps?v=2.0&key=eae3be059db26dc1f9cae1d1bee9d4cb"
+    ></script>
   </head>
   <body>
     <div id="app"></div>

+ 40 - 0
src/api/system.js

@@ -147,3 +147,43 @@ export function sysMenuTree(params) {
     params
   })
 }
+
+/** 获取授权牌模板列表 */
+export function fetchAuthTempList(params) {
+  return request({
+    url: '/auth/template/list',
+    method: 'get',
+    params
+  })
+}
+
+/** 添加编辑保存授权牌模板 */
+export function authTempSave(data) {
+  return request({
+    url: '/auth/template/save',
+    method: 'post',
+    data
+  })
+}
+
+/** 添加编辑保存授权牌模板 */
+export function authTempUpdate(data) {
+  // return request({
+  //   url: '/shop/authImage/update/all',
+  //   method: 'post',
+  //   data
+  // })
+  return fetch(`${process.env.VUE_APP_BASE_API}/shop/authImage/update/all`, {
+    body: JSON.stringify(data),
+    method: 'POST'
+  })
+}
+
+/** 获取机构可用模板(供应商可用模板) */
+export function authTempUsed(params) {
+  return request({
+    url: '/auth/template/form/data',
+    method: 'GET',
+    params
+  })
+}

BIN
src/assets/img/drag-auth-temp.jpg


BIN
src/assets/img/drag-qrcode-temp.png


+ 53 - 0
src/components/AuditButtonGroup/index.vue

@@ -0,0 +1,53 @@
+<template>
+  <div class="audit-button-group">
+    <el-badge :is-dot="isDot" class="mr-12">
+      <el-button type="primary" size="mini" @click="onClick('review')">查看</el-button>
+    </el-badge>
+    <template v-if="type === 'result'">
+      <el-button
+        :class="{ 'mr-12': marginRight }"
+        type="primary"
+        size="mini"
+        @click="onClick('result')"
+      >驳回</el-button>
+    </template>
+    <template v-if="type === 'audit'">
+      <el-button :class="{ 'mr-12': marginRight }" type="primary" size="mini" @click="onClick('audit')">审核</el-button>
+    </template>
+  </div>
+</template>
+<script>
+export default {
+  name: 'AuditButtonGroup',
+  props: {
+    isDot: {
+      type: Boolean,
+      default: false
+    },
+    type: {
+      type: String,
+      default: 'result',
+      validator: (value) => ['result', 'audit'].includes(value)
+    },
+    marginRight: {
+      type: Boolean,
+      default: false
+    }
+  },
+  methods: {
+    onClick(type) {
+      this.$emit('click', type)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.audit-button-group {
+  display: inline-block;
+
+  .mr-12 {
+    margin-right: 12px;
+  }
+}
+</style>

+ 30 - 0
src/components/AuditStatus/index.vue

@@ -0,0 +1,30 @@
+<template>
+  <div>
+    <span v-if="status === 2" class="status warning">待审核</span>
+    <span v-if="status === 1" class="status success">审核通过</span>
+    <!-- 未通过原因展示 -->
+    <template v-if="status === 0">
+      <el-popover placement="top-start" title="审核说明" width="400" trigger="hover" :content="reason">
+        <div slot="reference">
+          <span class="status danger">审核未通过</span>
+          <span class="el-icon-question status danger" />
+        </div>
+      </el-popover>
+    </template>
+  </div>
+</template>
+<script>
+export default {
+  name: 'AuditStatus',
+  props: {
+    status: {
+      type: Number,
+      default: 0
+    },
+    reason: {
+      type: String,
+      default: ''
+    }
+  }
+}
+</script>

+ 89 - 0
src/components/DragLayout/dragmove.js

@@ -0,0 +1,89 @@
+// https://github.com/knadh/dragmove.js
+// Kailash Nadh (c) 2020.
+// MIT License.
+
+let _loaded = false
+const _callbacks = []
+const _isTouch = window.ontouchstart !== undefined
+
+export const dragmove = function(target, handler, onStart, onEnd) {
+  // Register a global event to capture mouse moves (once).
+  if (!_loaded) {
+    document.addEventListener(_isTouch ? 'touchmove' : 'mousemove', function(e) {
+      let c = e
+      if (e.touches) {
+        c = e.touches[0]
+      }
+
+      // On mouse move, dispatch the coords to all registered callbacks.
+      for (var i = 0; i < _callbacks.length; i++) {
+        _callbacks[i](c.clientX, c.clientY)
+      }
+    })
+  }
+
+  _loaded = true
+  let isMoving = false
+  let hasStarted = false
+  let startX = 0
+  let startY = 0
+  let lastX = 0
+  let lastY = 0
+
+  // On the first click and hold, record the offset of the pointer in relation
+  // to the point of click inside the element.
+  handler.addEventListener(_isTouch ? 'touchstart' : 'mousedown', function(e) {
+    e.stopPropagation()
+    e.preventDefault()
+    if (target.dataset.dragEnabled === 'false') {
+      return
+    }
+
+    let c = e
+    if (e.touches) {
+      c = e.touches[0]
+    }
+
+    isMoving = true
+    startX = target.offsetLeft - c.clientX
+    startY = target.offsetTop - c.clientY
+  })
+
+  // On leaving click, stop moving.
+  document.addEventListener(_isTouch ? 'touchend' : 'mouseup', function(e) {
+    if (onEnd && hasStarted) {
+      onEnd(target, parseInt(target.style.left), parseInt(target.style.top))
+    }
+
+    isMoving = false
+    hasStarted = false
+  })
+
+  // Register mouse-move callback to move the element.
+  _callbacks.push(function move(x, y) {
+    if (!isMoving) {
+      return
+    }
+
+    if (!hasStarted) {
+      hasStarted = true
+      if (onStart) {
+        onStart(target, lastX, lastY)
+      }
+    }
+
+    lastX = x + startX
+    lastY = y + startY
+
+    // If boundary checking is on, don't let the element cross the viewport.
+    if (target.dataset.dragBoundary === 'true') {
+      lastX = Math.min(window.innerWidth - target.offsetWidth, Math.max(0, lastX))
+      lastY = Math.min(window.innerHeight - target.offsetHeight, Math.max(0, lastY))
+    }
+
+    target.style.left = lastX + 'px'
+    target.style.top = lastY + 'px'
+  })
+}
+
+export { dragmove as default }

+ 193 - 0
src/components/DragLayout/index.vue

@@ -0,0 +1,193 @@
+<template>
+  <div class="drag-layout">
+    <div class="drag-content" :class="{ padding: isDrag }">
+      <div id="drag__container" :style="imageStyle">
+        <div id="drag__move" :style="ewmStyle">
+          <el-tooltip v-model="tooltipShow" effect="dark" content="二维码在这里!" placement="top-start" :manual="true">
+            <div style="width: 100%; height: 100%" />
+          </el-tooltip>
+        </div>
+      </div>
+    </div>
+    <div class="drag__control">
+      <el-button @click="onCancel">取 消</el-button>
+      <el-button type="primary" @click="onConfirm">确 定</el-button>
+    </div>
+  </div>
+</template>
+
+<script>
+import { dragmove } from './dragmove.js'
+export default {
+  name: 'DragLayout',
+  props: {
+    qw: {
+      type: Number,
+      default: 53
+    },
+    qh: {
+      type: Number,
+      default: 53
+    },
+    oldX: {
+      type: Number,
+      default: 0
+    },
+    oldY: {
+      type: Number,
+      default: 0
+    },
+    image: {
+      type: String,
+      default: ''
+    },
+    size: {
+      type: String,
+      default: ''
+    },
+    isDrag: {
+      type: Boolean,
+      default: true
+    }
+  },
+  data() {
+    return {
+      tooltipShow: false,
+      dragContainer: null,
+      snapThreshold: 0, // 边界
+      x: 0,
+      y: 0
+    }
+  },
+  computed: {
+    imageWidth() {
+      return this.size.split(',')[0] + 'px'
+    },
+    imageHeight() {
+      return this.size.split(',')[1] + 'px'
+    },
+    imageStyle() {
+      return {
+        width: this.imageWidth,
+        height: this.imageHeight,
+        background: `url(${this.image}) no-repeat center`,
+        'background-size': `${this.imageWidth} ${this.imageHeight}`
+      }
+    },
+    ewmStyle() {
+      console.log({
+        left: this.oldX + 'px',
+        top: this.oldY + 'px',
+        width: this.qw + 'px',
+        height: this.qh + 'px',
+        'background-size': `${this.qw + 'px'} ${this.qh + 'px'}`
+      })
+
+      return {
+        // cursor: this.isDrag ? 'move' : '',
+        left: this.oldX + 'px',
+        top: this.oldY + 'px',
+        width: this.qw + 'px',
+        height: this.qh + 'px',
+        'background-size': `${this.qw + 'px'} ${this.qh + 'px'}`
+      }
+    }
+  },
+  mounted() {
+    if (!this.isDrag) return
+    this.dragContainer = document.querySelector('#drag__container')
+    dragmove(
+      document.querySelector('#drag__container #drag__move'),
+      document.querySelector('#drag__container #drag__move'),
+      this.onStart,
+      this.onEnd
+    )
+    setTimeout(() => {
+      this.tooltipShow = true
+    }, 2000)
+  },
+  methods: {
+    // 取消
+    onCancel() {
+      this.x = this.oldX
+      this.y = this.oldY
+      this.$emit('cancel', { x: this.x, y: this.y })
+      this.tooltipShow = false
+    },
+
+    // 确认
+    onConfirm() {
+      this.$emit('confirm', { x: this.x, y: this.y })
+      this.tooltipShow = false
+    },
+
+    // 开始拖动
+    onStart(el, x, y) {
+      this.tooltipShow = false
+    },
+
+    // 结束拖动
+    onEnd(el, x, y) {
+      this.tooltipShow = true
+      if (x < this.snapThreshold) {
+        el.style.left = 0
+        el.style.right = 'auto'
+      }
+      if (y < 0) {
+        el.style.top = 0
+        el.style.bottom = 'auto'
+      }
+      if (x > this.dragContainer.offsetWidth - el.offsetWidth) {
+        el.style.right = 0
+        el.style.left = 'auto'
+      }
+      if (y > this.dragContainer.offsetHeight - el.offsetHeight) {
+        el.style.bottom = 0
+        el.style.top = 'auto'
+      }
+
+      const { offsetWidth, offsetHeight } = this.dragContainer
+
+      if (x < 0) {
+        this.x = 0
+      } else if (x > offsetWidth - this.qw) {
+        this.x = offsetWidth - this.qw
+      } else {
+        this.x = x
+      }
+
+      if (y < 0) {
+        this.y = 0
+      } else if (y > offsetHeight - this.qh) {
+        this.y = offsetHeight - this.qh
+      } else {
+        this.y = y
+      }
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.drag-content {
+  background: #f1f1f1;
+  &.padding {
+    padding: 50px 0;
+  }
+  #drag__container {
+    position: relative;
+    margin: 0 auto;
+    overflow: hidden;
+    background: #fff;
+  }
+  #drag__move {
+    position: absolute;
+    background-color: skyblue;
+    background: url(~@/assets/img/drag-qrcode-temp.png) no-repeat center;
+  }
+}
+
+.drag__control {
+  margin-top: 24px;
+  text-align: right;
+}
+</style>

+ 12 - 13
src/components/IconList/index.vue

@@ -10,7 +10,7 @@
               </div>
               <div class="icon-item">
                 <svg-icon :icon-class="item" class-name="disabled" />
-                <span>{{ item }}</span>
+                <!-- <span>{{ item }}</span> -->
               </div>
             </el-tooltip>
           </div>
@@ -25,7 +25,7 @@
               </div>
               <div class="icon-item">
                 <i :class="'el-icon-' + item" />
-                <span>{{ item }}</span>
+                <!-- <span>{{ item }}</span> -->
               </div>
             </el-tooltip>
           </div>
@@ -40,7 +40,7 @@
               </div>
               <div class="icon-item">
                 <i :class="'iconfont ' + item" />
-                <span>{{ item }}</span>
+                <!-- <span>{{ item }}</span> -->
               </div>
             </el-tooltip>
           </div>
@@ -73,27 +73,26 @@ export default {
 
 <style lang="scss" scoped>
 .icons-container {
-  margin: 10px 20px 0;
   overflow: hidden;
 
   .el-tab-pane{
-    max-height: 500px;
+    max-height: 400px;
     overflow-y: auto;
   }
 
   .grid {
     position: relative;
     display: grid;
-    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
+    grid-template-columns: repeat(auto-fill, minmax(40px, 1fr));
   }
   .icon-item {
-    padding-top: 8px;
-    margin: 16px;
-    height: 80px;
+    padding-top: 4px;
+    margin: 8px;
+    height: 30px;
+    width: 30px;
     text-align: center;
-    width: 100px;
     float: left;
-    font-size: 28px;
+    font-size: 16px;
     color: #24292e;
     cursor: pointer;
     &:hover{
@@ -102,8 +101,8 @@ export default {
   }
   span {
     display: block;
-    font-size: 16px;
-    margin-top: 10px;
+    font-size: 12px;
+    margin-top: 8px;
   }
   .disabled {
     pointer-events: none;

+ 1 - 1
src/components/Pagination/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div :class="{'hidden':hidden}" class="pagination-container">
+  <div v-show="total > limit" :class="{'hidden':hidden}" class="pagination-container">
     <el-pagination
       :background="background"
       :current-page.sync="currentPage"

+ 44 - 0
src/components/SimpleAMap/common/utils.js

@@ -0,0 +1,44 @@
+export function initGeocoder() {
+  return new Promise((resolve, reject) => {
+    window.AMap.plugin('AMap.Geocoder', () => {
+      try {
+        const geocoder = new window.AMap.Geocoder({
+          // city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
+          city: '全国'
+        })
+        resolve(geocoder)
+      } catch (error) {
+        reject(error)
+      }
+    })
+  })
+}
+
+export function geolocation() {
+  return new Promise((resolve, reject) => {
+    window.AMap.plugin('AMap.Geolocation', () => {
+      const geolocation = new window.AMap.Geolocation({
+        // 是否使用高精度定位,默认:true
+        enableHighAccuracy: true,
+        // 设置定位超时时间,默认:无穷大
+        timeout: 10000,
+        // 定位按钮的停靠位置的偏移量
+        offset: [10, 20],
+        //  定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false
+        zoomToAccuracy: true,
+        //  定位按钮的排放位置,  RB表示右下
+        position: 'RB'
+      })
+
+      geolocation.getCurrentPosition((status, result) => {
+        if (status === 'complete') {
+          resolve(result)
+        } else {
+          reject(result)
+        }
+      })
+    })
+  })
+}
+
+export default {}

+ 157 - 0
src/components/SimpleAMap/index.vue

@@ -0,0 +1,157 @@
+<template>
+  <div id="aMap" class="a-map" />
+</template>
+
+<script>
+import { geolocation, initGeocoder } from './common/utils'
+export default {
+  name: 'AMap',
+  props: {
+    zoom: {
+      type: Number,
+      default: 17
+    },
+    markerIcon: {
+      type: String,
+      default: '/location.png'
+    },
+    center: {
+      type: Boolean,
+      default: false
+    },
+    address: {
+      type: String,
+      default: ''
+    },
+    lnglat: {
+      type: Array,
+      default: null
+    }
+  },
+  data() {
+    return {
+      marker: null,
+      map: null,
+      timer: null,
+      geocoder: null
+    }
+  },
+  methods: {
+    async init() {
+      if (this.lnglat) {
+        console.log('使用经纬度定位')
+        this.initMap(this.lnglat)
+      } else if (this.address) {
+        console.log('使用地址定位')
+        this.initGeocoder()
+      } else {
+        console.log('使用高精度自动定位')
+        this.geolocation()
+      }
+    },
+    // 高精度定位
+    async geolocation() {
+      try {
+        const result = await geolocation()
+        this.$emit('position', {
+          lng: result.position.lng,
+          lat: result.position.lat
+        })
+        this.initMap(result.position)
+      } catch (error) {
+        this.initMap()
+        alert('获取当前位置信息失败,已为您定位到当前城市!')
+        console.log('获取当前位置信息失败,已为您定位到当前城市!')
+      }
+    },
+    // 根据地址信息定位
+    async initGeocoder() {
+      try {
+        this.geocoder = await initGeocoder()
+        this.geocoder.getLocation(this.address, (status, result) => {
+          if (status === 'complete' && result.info === 'OK') {
+            const position = result.geocodes[0].location
+            this.initMap(position)
+            this.$emit('position', {
+              lng: position.lng,
+              lat: position.lat
+            })
+          } else {
+            console.log(result)
+          }
+        })
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 初始化地图
+    initMap(position) {
+      this.map = new window.AMap.Map('aMap', {
+        viewMode: '2D', // 默认使用 2D 模式,如果希望使用带有俯仰角的 3D 模式,请设置 viewMode: '3D',
+        zoom: this.zoom, // 初始化地图层级
+        center: position // 初始化地图中心点
+      })
+      this.map.on('click', this.onMapClick)
+      if (position) {
+        this.map.add(this.initMarker(position))
+      }
+      this.initMapControl()
+    },
+    // 初始化标记点
+    initMarker(position) {
+      this.marker = new window.AMap.Marker({
+        icon: this.markerIcon,
+        position,
+        anchor: 'bottom-center',
+        draggable: true
+      })
+      this.marker.on('dragging', this.moveMarker)
+      return this.marker
+    },
+    // 修改标记点
+    onMapClick(map) {
+      if (this.marker) this.map.remove(this.marker)
+      if (this.center) this.map.setCenter(map.lnglat)
+      this.map.add(this.initMarker(map.lnglat))
+      this.$emit('position', {
+        lng: map.lnglat.lng,
+        lat: map.lnglat.lat
+      })
+    },
+    // 标记点移动
+    moveMarker(marker) {
+      if (this.timer) clearTimeout(this.timer)
+      this.timer = setTimeout(() => {
+        if (this.center) this.map.setCenter(marker.lnglat)
+        this.$emit('position', {
+          lng: marker.lnglat.lng,
+          lat: marker.lnglat.lat
+        })
+      }, 200)
+    },
+    // 地图控件
+    initMapControl() {
+      window.AMap.plugin(['AMap.ToolBar', 'AMap.Scale', 'AMap.MapType', 'AMap.Geolocation'], () => {
+        // 在图面添加工具条控件,工具条控件集成了缩放、平移、定位等功能按钮在内的组合控件
+        this.map.addControl(new window.AMap.ToolBar())
+
+        // 在图面添加比例尺控件,展示地图在当前层级和纬度下的比例尺
+        this.map.addControl(new window.AMap.Scale())
+
+        // 在图面添加类别切换控件,实现默认图层与卫星图、实施交通图层之间切换的控制
+        this.map.addControl(new window.AMap.MapType())
+
+        // 在图面添加定位控件,用来获取和展示用户主机所在的经纬度位置
+        // this.map.addControl(new window.AMap.Geolocation())
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+#aMap {
+  height: 100%;
+  min-height: 400px;
+}
+</style>

+ 13 - 0
src/components/index.js

@@ -0,0 +1,13 @@
+import AuditStatus from './AuditStatus'
+import AuditButtonGroup from './AuditButtonGroup'
+import Pagination from './Pagination'
+
+const install = (Vue) => {
+  Vue.component(AuditStatus.name, AuditStatus)
+  Vue.component(AuditButtonGroup.name, AuditButtonGroup)
+  Vue.component(Pagination.name, Pagination)
+}
+
+export default {
+  install
+}

+ 34 - 22
src/components/qrcode/index.vue

@@ -9,15 +9,16 @@
       <div class="btn down-btn" @click="handleDown">下载二维码</div>
       <div class="btn close-btn" @click="handleClose">关闭</div>
     </div>
-    <canvas id="canvas" style="display:none" />
+    <canvas id="canvas" style="display: none" />
     <div v-if="isVisible" class="mask" @click="handleClose" />
-    <a id="downloadLink" href="#" style="display:none" />
+    <a id="downloadLink" href="#" style="display: none" />
   </div>
 </template>
 
 <script>
 import QRCode from 'qrcode'
 import downImage from '@/assets/img/qrcode-bg-down.jpg'
+import { mapGetters } from 'vuex'
 export default {
   name: 'Qrcode',
   props: {
@@ -34,9 +35,13 @@ export default {
     return {
       imgUrl: '',
       wwwServer: process.env.VUE_APP_BASE_SERVER,
+      wwwHost: process.env.VUE_APP_WWW_HOST,
       qrcodePath: ''
     }
   },
+  computed: {
+    ...mapGetters(['authUserId'])
+  },
   created() {
     this.initQrcode()
   },
@@ -60,7 +65,11 @@ export default {
     // 初始化二维码
     async initQrcode() {
       console.log(this.productInfo)
-      this.qrcodePath = `${this.wwwServer}/product/auth/product-${this.productInfo?.productId}.html`
+      if (this.authUserId === 12) {
+        this.qrcodePath = `${this.wwwHost}/12/ross/approve/device/detail?id=${this.productInfo?.productId}`
+      } else {
+        this.qrcodePath = `${this.wwwServer}/product/auth/product-${this.productInfo?.productId}.html`
+      }
       // 二维码配置
       const options = {
         width: 192,
@@ -75,7 +84,11 @@ export default {
     },
     // 生成下载的文件
     async createDownFile(callback) {
-      this.qrcodePath = `${this.wwwServer}/product/auth/product-${this.productInfo?.productId}.html`
+      if (this.authUserId === 12) {
+        this.qrcodePath = `${this.wwwHost}/12/ross/approve/device/detail?id=${this.productInfo?.productId}`
+      } else {
+        this.qrcodePath = `${this.wwwServer}/product/auth/product-${this.productInfo?.productId}.html`
+      }
       const strHeader = this.productInfo.productName
       const strFooter1 = '仪器SN码:'
       const strFooter2 = this.hanldeSNcode(this.productInfo.snCode)
@@ -117,7 +130,7 @@ export default {
         let temp = ''
         const row = []
         for (let a = 0; a < chr.length; a++) {
-          if (ctx.measureText(temp).width >= (w - 290)) {
+          if (ctx.measureText(temp).width >= w - 290) {
             row.push(temp)
             temp = ''
           }
@@ -150,20 +163,20 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-.code-container{
+.code-container {
   position: relative;
   z-index: 999999;
 }
-.mask{
+.mask {
   position: fixed;
   top: 0;
   left: 0;
   z-index: 999998;
   width: 100vw;
   height: 100vh;
-  background: rgba(0,0,0,.5);
+  background: rgba(0, 0, 0, 0.5);
 }
-.qrcode{
+.qrcode {
   z-index: 999999;
   position: fixed;
   left: 50%;
@@ -172,31 +185,31 @@ export default {
   width: 300px;
   height: 400px;
   background: url(../../assets/img/qrcode-bg-show.png) no-repeat center;
-  .content{
+  .content {
     width: 192px;
     height: 192px;
     position: absolute;
     left: 54px;
     bottom: 46px;
   }
-  .down-btn{
+  .down-btn {
     left: 0;
   }
-  .close-btn{
+  .close-btn {
     right: 0;
   }
-  .title{
+  .title {
     position: absolute;
     top: 32px;
     left: 50%;
     transform: translateX(-50%);
-    width:256px;
+    width: 256px;
     text-align: center;
     font-size: 16px;
     color: #fff;
     font-weight: bold;
   }
-  .sncode{
+  .sncode {
     position: absolute;
     top: 78px;
     left: 50%;
@@ -205,19 +218,18 @@ export default {
     width: 192px;
     color: #0e9ef0;
     font-size: 14px;
-    span{
+    span {
       font-weight: bold;
     }
   }
-
 }
-.btn  {
+.btn {
   position: absolute;
   bottom: -60px;
-	width: 108px;
-	height: 32px;
-	background-image: linear-gradient(-90deg,	#50c0ff 0%,#0e90dc 100%);
-	border-radius: 4px;
+  width: 108px;
+  height: 32px;
+  background-image: linear-gradient(-90deg, #50c0ff 0%, #0e90dc 100%);
+  border-radius: 4px;
   text-align: center;
   line-height: 32px;
   color: #fff;

+ 6 - 3
src/main.js

@@ -8,6 +8,8 @@ import Element from 'element-ui'
 import './styles/element-variables.scss'
 import '@/styles/index.scss' // global css
 
+import MyComponents from './components'
+
 import App from './App'
 import store from './store'
 import router from './router'
@@ -20,15 +22,16 @@ import './mixin/base' // 公共方法
 
 Vue.use(Element, {
   size: Cookies.get('size') || 'medium' // set element-ui default size
-  // locale: enLang // 如果使用中文,无需设置,请删除
 })
 
+Vue.use(MyComponents)
+
 window.addEventListener('popstate', function() {
   history.pushState(null, null, document.URL)
 })
 
 // register global utility filters
-Object.keys(filters).forEach(key => {
+Object.keys(filters).forEach((key) => {
   Vue.filter(key, filters[key])
 })
 
@@ -38,5 +41,5 @@ new Vue({
   el: '#app',
   router,
   store,
-  render: h => h(App)
+  render: (h) => h(App)
 })

+ 0 - 5
src/permission.js

@@ -15,7 +15,6 @@ const shareList = ['Share', 'SharePayVip', 'SharePaySuccess', 'SharePayFaild']
 
 // 路由拦截器
 router.beforeEach(async(to, from, next) => {
-  // 获取token
   const hasToken = getToken()
   // 设置页面标题
   // document.title = getPageTitle(to.meta.title)
@@ -25,16 +24,12 @@ router.beforeEach(async(to, from, next) => {
   }
 
   if (hasToken) {
-    // 如果是访问登录页面,强制跳转到首页
     if (to.path === '/login') {
       next({ path: initGoPage() })
     } else {
-      // 加载国家列表并保存到store
       store.dispatch('app/setCountry')
-      // 判断当前用户是否拥有角色
       const hasRoles = store.getters.roles && store.getters.roles.length > 0
       if (hasRoles) {
-        // 放行
         next()
       } else {
         try {

+ 2 - 0
src/router/index.js

@@ -26,6 +26,7 @@ import normalPersonal from './module/normal/personal'
 import normalPersonnel from './module/normal/personnel'
 import normalVip from './module/normal/vip'
 import normalUser from './module/normal/user'
+import normalSettings from './module/normal/settings'
 
 // 需要权限访问的路由列表
 export const asyncRoutes = [
@@ -41,6 +42,7 @@ export const asyncRoutes = [
   ...normalMaterial,
   ...normalPersonal,
   ...normalPersonnel,
+  ...normalSettings,
   ...normalUser
 ]
 

+ 7 - 35
src/router/module/admin/settings.js

@@ -15,41 +15,6 @@ const settingRoutes = [
         meta: { title: '菜单管理', noCache: true },
         component: () => import('@/views/admin/settings/menus')
       },
-      {
-        path: 'menus/add',
-        name: 'SettingsMenusAdd',
-        hidden: true,
-        meta: { title: '添加菜单', noCache: true },
-        component: () => import('@/views/admin/settings/menus/edit')
-      },
-      {
-        path: 'menus/edit',
-        name: 'SettingsMenusEdit',
-        hidden: true,
-        meta: { title: '修改菜单', noCache: true },
-        component: () => import('@/views/admin/settings/menus/edit')
-      },
-      {
-        path: 'menus/children/:menuType/:id/:title',
-        name: 'SettingsChildrenMenus',
-        hidden: true,
-        meta: { title: '子菜单管理', noCache: false },
-        component: () => import('@/views/admin/settings/menus/children-list')
-      },
-      {
-        path: 'menus/children/add',
-        name: 'SettingsChildrenMenusAdd',
-        hidden: true,
-        meta: { title: '添加子菜单', noCache: true },
-        component: () => import('@/views/admin/settings/menus/edit')
-      },
-      {
-        path: 'menus/children/edit',
-        name: 'SettingsChildrenMenusEdit',
-        hidden: true,
-        meta: { title: '修改子菜单', noCache: true },
-        component: () => import('@/views/admin/settings/menus/edit')
-      },
       {
         path: 'roles',
         name: 'SettingsRoles',
@@ -89,6 +54,13 @@ const settingRoutes = [
         hidden: true,
         meta: { title: '修改用户', noCache: true },
         component: () => import('@/views/admin/settings/accounts/edit')
+      },
+      {
+        path: 'auth-card',
+        name: 'SettingsAuthCard',
+        hidden: true,
+        meta: { title: '授权牌模板', noCache: true },
+        component: () => import('@/views/admin/settings/auth-card')
       }
     ]
   }

+ 63 - 0
src/router/module/normal/settings.js

@@ -0,0 +1,63 @@
+/* Layout */
+import Layout from '@/layout'
+
+const settingRoutes = [
+  {
+    path: '/normal/settings',
+    component: Layout,
+    redirect: '/normal/settings/auth-card',
+    name: 'NormalSettings',
+    meta: { title: '系统设置', icon: 'el-icon-s-tools', noCache: true },
+    children: [
+      {
+        path: 'roles',
+        name: 'NormalSettingsRoles',
+        meta: { title: '角色管理', noCache: true },
+        component: () => import('@/views/normal/settings/roles')
+      },
+      {
+        path: 'roles/add',
+        name: 'NormalSettingsRolesAdd',
+        hidden: true,
+        meta: { title: '添加角色', noCache: true },
+        component: () => import('@/views/normal/settings/roles/edit')
+      },
+      {
+        path: 'roles/edit',
+        name: 'NormalSettingsRolesEdit',
+        hidden: true,
+        meta: { title: '修改角色', noCache: true },
+        component: () => import('@/views/normal/settings/roles/edit')
+      },
+      {
+        path: 'accounts',
+        name: 'NormalSettingsAccounts',
+        meta: { title: '用户管理', noCache: true },
+        component: () => import('@/views/normal/settings/accounts')
+      },
+      {
+        path: 'accounts/add',
+        name: 'NormalSettingsAccountsAdd',
+        hidden: true,
+        meta: { title: '添加用户', noCache: true },
+        component: () => import('@/views/normal/settings/accounts/edit')
+      },
+      {
+        path: 'accounts/edit',
+        name: 'NormalSettingsAccountsEdit',
+        hidden: true,
+        meta: { title: '修改用户', noCache: true },
+        component: () => import('@/views/normal/settings/accounts/edit')
+      },
+      {
+        path: 'auth-card',
+        name: 'NormalSettingsAuthCard',
+        hidden: true,
+        meta: { title: '授权牌模板', noCache: false },
+        component: () => import('@/views/normal/settings/auth-card')
+      }
+    ]
+  }
+]
+
+export default settingRoutes

+ 0 - 104
src/router/router-map.js

@@ -1,104 +0,0 @@
-// 审核管理
-const audit = [
-  {
-    id: 1,
-    name: '审核管理',
-    children: [
-      { id: 1, name: '机构认证审核' },
-      { id: 2, name: '机构认证审核详情' },
-      { id: 3, name: '设备审核列表' },
-      { id: 4, name: '设备审核详情' },
-      { id: 5, name: '医师审核列表' },
-      { id: 6, name: '医师审核详情' },
-      { id: 7, name: '文章审核列表' },
-      { id: 8, name: '审核文章' },
-      { id: 9, name: '图片审核列表' },
-      { id: 10, name: '审核图片' },
-      { id: 11, name: '视频审核列表' },
-      { id: 12, name: '文件审核列表' }
-    ]
-  }
-]
-// 机构认证
-const club = [
-  {
-    id: 2,
-    name: '机构认证',
-    children: [
-      { id: 1, name: '机构列表' },
-      { id: 2, name: '添加机构' },
-      { id: 3, name: '修改机构' },
-      { id: 4, name: '登录用户' },
-      { id: 5, name: '设备列表' },
-      { id: 6, name: '添加设备' },
-      { id: 7, name: '修改设备' }
-    ]
-  }
-]
-// 医师认证
-const doctor = [
-  {
-    id: 3,
-    name: '医师认证',
-    children: [
-      { id: 1, name: '医师列表' },
-      { id: 2, name: '添加医师' },
-      { id: 3, name: '修改医师资料' }
-    ]
-  }
-]
-// 用户反馈
-const feedback = [
-  {
-    id: 4,
-    name: '用户反馈',
-    children: [
-      { id: 1, name: '反馈列表' },
-      { id: 2, name: '反馈处理' }
-    ]
-  }
-]
-// 新手帮助
-const helper = [
-  {
-    id: 5,
-    name: '新手帮助',
-    children: [
-      { id: 1, name: '视频教程' },
-      { id: 2, name: '文档教程' }
-    ]
-  }
-]
-// 资料库
-const material = [
-  {
-    id: 6,
-    name: '资料库',
-    children: [
-      { id: 1, name: '文章列表' },
-      { id: 2, name: '编辑文章' },
-      { id: 3, name: '图片列表' },
-      { id: 4, name: '编辑图片' },
-      { id: 5, name: '视频列表' },
-      { id: 6, name: '文件列表' }
-    ]
-  }
-]
-// 账号管理
-const supplier = [
-  {
-    id: 7,
-    name: '账号管理',
-    children: [
-      { id: 1, name: '供应商账号' },
-      { id: 2, name: '添加供应商' },
-      { id: 3, name: '修改供应商' },
-      { id: 4, name: '查看认证机构' },
-      { id: 5, name: '认证机构详情' },
-      { id: 6, name: '查看设备认证' },
-      { id: 7, name: '设备认证详情' }
-    ]
-  }
-]
-
-export default [...audit, ...club, ...doctor, ...feedback, ...helper, ...material, ...supplier]

+ 0 - 692
src/styles/index.css

@@ -1,692 +0,0 @@
-:export {
-  menuText: #bfcbd9;
-  menuActiveText: #409EFF;
-  subMenuActiveText: #f4f4f5;
-  menuBg: #304156;
-  menuHover: #263445;
-  subMenuBg: #1f2d3d;
-  subMenuHover: #001528;
-  sideBarWidth: 210px;
-}
-
-/* fade */
-.fade-enter-active,
-.fade-leave-active {
-  transition: opacity 0.28s;
-}
-
-.fade-enter,
-.fade-leave-active {
-  opacity: 0;
-}
-
-/* fade-transform */
-.fade-transform-leave-active,
-.fade-transform-enter-active {
-  transition: all .5s;
-}
-
-.fade-transform-enter {
-  opacity: 0;
-  transform: translateX(-30px);
-}
-
-.fade-transform-leave-to {
-  opacity: 0;
-  transform: translateX(30px);
-}
-
-/* breadcrumb transition */
-.breadcrumb-enter-active,
-.breadcrumb-leave-active {
-  transition: all .5s;
-}
-
-.breadcrumb-enter,
-.breadcrumb-leave-active {
-  opacity: 0;
-  transform: translateX(20px);
-}
-
-.breadcrumb-move {
-  transition: all .5s;
-}
-
-.breadcrumb-leave-active {
-  position: absolute;
-}
-
-.el-breadcrumb__inner,
-.el-breadcrumb__inner a {
-  font-weight: 400 !important;
-}
-
-.el-upload input[type="file"] {
-  display: none !important;
-}
-
-.el-upload__input {
-  display: none;
-}
-
-.cell .el-tag {
-  margin-right: 0px;
-}
-
-.small-padding .cell {
-  padding-left: 5px;
-  padding-right: 5px;
-}
-
-.fixed-width .el-button--mini {
-  padding: 7px 10px;
-  min-width: 60px;
-}
-
-.status-col .cell {
-  padding: 0 10px;
-  text-align: center;
-}
-
-.status-col .cell .el-tag {
-  margin-right: 0px;
-}
-
-.el-dialog {
-  transform: none;
-  left: 0;
-  position: relative;
-  margin: 0 auto;
-}
-
-.upload-container .el-upload {
-  width: 100%;
-}
-
-.upload-container .el-upload .el-upload-dragger {
-  width: 100%;
-  height: 200px;
-}
-
-.el-dropdown-menu a {
-  display: block;
-}
-
-.el-range-editor.el-input__inner {
-  display: inline-flex !important;
-}
-
-.el-range-separator {
-  box-sizing: content-box;
-}
-
-#app .main-container {
-  min-height: 100%;
-  transition: margin-left .28s;
-  margin-left: 210px;
-  position: relative;
-}
-
-#app .sidebar-container {
-  transition: width 0.28s;
-  width: 210px !important;
-  background-color: #304156;
-  height: 100%;
-  position: fixed;
-  font-size: 0px;
-  top: 0;
-  bottom: 0;
-  left: 0;
-  z-index: 1001;
-  overflow: hidden;
-}
-
-#app .sidebar-container .horizontal-collapse-transition {
-  transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
-}
-
-#app .sidebar-container .scrollbar-wrapper {
-  overflow-x: hidden !important;
-}
-
-#app .sidebar-container .el-scrollbar__bar.is-vertical {
-  right: 0px;
-}
-
-#app .sidebar-container .el-scrollbar {
-  height: 100%;
-}
-
-#app .sidebar-container.has-logo .el-scrollbar {
-  height: calc(100% - 50px);
-}
-
-#app .sidebar-container .is-horizontal {
-  display: none;
-}
-
-#app .sidebar-container a {
-  display: inline-block;
-  width: 100%;
-  overflow: hidden;
-}
-
-#app .sidebar-container .svg-icon {
-  margin-right: 16px;
-}
-
-#app .sidebar-container .sub-el-icon {
-  margin-right: 12px;
-  margin-left: -2px;
-}
-
-#app .sidebar-container .el-menu {
-  border: none;
-  height: 100%;
-  width: 100% !important;
-}
-
-#app .sidebar-container .submenu-title-noDropdown:hover,
-#app .sidebar-container .el-submenu__title:hover {
-  background-color: #263445 !important;
-}
-
-#app .sidebar-container .is-active > .el-submenu__title {
-  color: #f4f4f5 !important;
-}
-
-#app .sidebar-container .nest-menu .el-submenu > .el-submenu__title,
-#app .sidebar-container .el-submenu .el-menu-item {
-  min-width: 210px !important;
-  background-color: #1f2d3d !important;
-}
-
-#app .sidebar-container .nest-menu .el-submenu > .el-submenu__title:hover,
-#app .sidebar-container .el-submenu .el-menu-item:hover {
-  background-color: #001528 !important;
-}
-
-#app .hideSidebar .sidebar-container {
-  width: 54px !important;
-}
-
-#app .hideSidebar .main-container {
-  margin-left: 54px;
-}
-
-#app .hideSidebar .submenu-title-noDropdown {
-  padding: 0 !important;
-  position: relative;
-}
-
-#app .hideSidebar .submenu-title-noDropdown .el-tooltip {
-  padding: 0 !important;
-}
-
-#app .hideSidebar .submenu-title-noDropdown .el-tooltip .svg-icon {
-  margin-left: 20px;
-}
-
-#app .hideSidebar .submenu-title-noDropdown .el-tooltip .sub-el-icon {
-  margin-left: 19px;
-}
-
-#app .hideSidebar .el-submenu {
-  overflow: hidden;
-}
-
-#app .hideSidebar .el-submenu > .el-submenu__title {
-  padding: 0 !important;
-}
-
-#app .hideSidebar .el-submenu > .el-submenu__title .svg-icon {
-  margin-left: 20px;
-}
-
-#app .hideSidebar .el-submenu > .el-submenu__title .sub-el-icon {
-  margin-left: 19px;
-}
-
-#app .hideSidebar .el-submenu > .el-submenu__title .el-submenu__icon-arrow {
-  display: none;
-}
-
-#app .hideSidebar .el-menu--collapse .el-submenu > .el-submenu__title > span {
-  height: 0;
-  width: 0;
-  overflow: hidden;
-  visibility: hidden;
-  display: inline-block;
-}
-
-#app .el-menu--collapse .el-menu .el-submenu {
-  min-width: 210px !important;
-}
-
-#app .mobile .main-container {
-  margin-left: 0px;
-}
-
-#app .mobile .sidebar-container {
-  transition: transform .28s;
-  width: 210px !important;
-}
-
-#app .mobile.hideSidebar .sidebar-container {
-  pointer-events: none;
-  transition-duration: 0.3s;
-  transform: translate3d(-210px, 0, 0);
-}
-
-#app .withoutAnimation .main-container,
-#app .withoutAnimation .sidebar-container {
-  transition: none;
-}
-
-.el-menu--vertical > .el-menu .svg-icon {
-  margin-right: 16px;
-}
-
-.el-menu--vertical > .el-menu .sub-el-icon {
-  margin-right: 12px;
-  margin-left: -2px;
-}
-
-.el-menu--vertical .nest-menu .el-submenu > .el-submenu__title:hover,
-.el-menu--vertical .el-menu-item:hover {
-  background-color: #263445 !important;
-}
-
-.el-menu--vertical > .el-menu--popup {
-  max-height: 100vh;
-  overflow-y: auto;
-}
-
-.el-menu--vertical > .el-menu--popup::-webkit-scrollbar-track-piece {
-  background: #d3dce6;
-}
-
-.el-menu--vertical > .el-menu--popup::-webkit-scrollbar {
-  width: 6px;
-}
-
-.el-menu--vertical > .el-menu--popup::-webkit-scrollbar-thumb {
-  background: #99a9bf;
-  border-radius: 20px;
-}
-
-:export {
-  menuText: #bfcbd9;
-  menuActiveText: #409EFF;
-  subMenuActiveText: #f4f4f5;
-  menuBg: #304156;
-  menuHover: #263445;
-  subMenuBg: #1f2d3d;
-  subMenuHover: #001528;
-  sideBarWidth: 210px;
-}
-
-.blue-btn {
-  background: #324157;
-}
-
-.blue-btn:hover {
-  color: #324157;
-}
-
-.blue-btn:hover:before, .blue-btn:hover:after {
-  background: #324157;
-}
-
-.light-blue-btn {
-  background: #3A71A8;
-}
-
-.light-blue-btn:hover {
-  color: #3A71A8;
-}
-
-.light-blue-btn:hover:before, .light-blue-btn:hover:after {
-  background: #3A71A8;
-}
-
-.red-btn {
-  background: #C03639;
-}
-
-.red-btn:hover {
-  color: #C03639;
-}
-
-.red-btn:hover:before, .red-btn:hover:after {
-  background: #C03639;
-}
-
-.pink-btn {
-  background: #E65D6E;
-}
-
-.pink-btn:hover {
-  color: #E65D6E;
-}
-
-.pink-btn:hover:before, .pink-btn:hover:after {
-  background: #E65D6E;
-}
-
-.green-btn {
-  background: #30B08F;
-}
-
-.green-btn:hover {
-  color: #30B08F;
-}
-
-.green-btn:hover:before, .green-btn:hover:after {
-  background: #30B08F;
-}
-
-.tiffany-btn {
-  background: #4AB7BD;
-}
-
-.tiffany-btn:hover {
-  color: #4AB7BD;
-}
-
-.tiffany-btn:hover:before, .tiffany-btn:hover:after {
-  background: #4AB7BD;
-}
-
-.yellow-btn {
-  background: #FEC171;
-}
-
-.yellow-btn:hover {
-  color: #FEC171;
-}
-
-.yellow-btn:hover:before, .yellow-btn:hover:after {
-  background: #FEC171;
-}
-
-.pan-btn {
-  font-size: 14px;
-  color: #fff;
-  padding: 14px 36px;
-  border-radius: 8px;
-  border: none;
-  outline: none;
-  transition: 600ms ease all;
-  position: relative;
-  display: inline-block;
-}
-
-.pan-btn:hover {
-  background: #fff;
-}
-
-.pan-btn:hover:before, .pan-btn:hover:after {
-  width: 100%;
-  transition: 600ms ease all;
-}
-
-.pan-btn:before, .pan-btn:after {
-  content: '';
-  position: absolute;
-  top: 0;
-  right: 0;
-  height: 2px;
-  width: 0;
-  transition: 400ms ease all;
-}
-
-.pan-btn::after {
-  right: inherit;
-  top: inherit;
-  left: 0;
-  bottom: 0;
-}
-
-.custom-button {
-  display: inline-block;
-  line-height: 1;
-  white-space: nowrap;
-  cursor: pointer;
-  background: #fff;
-  color: #fff;
-  -webkit-appearance: none;
-  text-align: center;
-  box-sizing: border-box;
-  outline: 0;
-  margin: 0;
-  padding: 10px 15px;
-  font-size: 14px;
-  border-radius: 4px;
-}
-
-body {
-  height: 100%;
-  -moz-osx-font-smoothing: grayscale;
-  -webkit-font-smoothing: antialiased;
-  text-rendering: optimizeLegibility;
-  font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
-}
-
-label {
-  font-weight: 700;
-}
-
-html {
-  height: 100%;
-  box-sizing: border-box;
-}
-
-#app {
-  height: 100%;
-}
-
-*,
-*:before,
-*:after {
-  box-sizing: inherit;
-}
-
-.no-padding {
-  padding: 0px !important;
-}
-
-.padding-content {
-  padding: 4px 0;
-}
-
-a:focus,
-a:active {
-  outline: none;
-}
-
-a,
-a:focus,
-a:hover {
-  cursor: pointer;
-  color: inherit;
-  text-decoration: none;
-}
-
-div:focus {
-  outline: none;
-}
-
-.fr {
-  float: right;
-}
-
-.fl {
-  float: left;
-}
-
-.pr-5 {
-  padding-right: 5px;
-}
-
-.pl-5 {
-  padding-left: 5px;
-}
-
-.block {
-  display: block;
-}
-
-.pointer {
-  cursor: pointer;
-}
-
-.inlineBlock {
-  display: block;
-}
-
-.clearfix:after {
-  visibility: hidden;
-  display: block;
-  font-size: 0;
-  content: " ";
-  clear: both;
-  height: 0;
-}
-
-aside {
-  background: #eef1f6;
-  padding: 8px 24px;
-  margin-bottom: 20px;
-  border-radius: 2px;
-  display: block;
-  line-height: 32px;
-  font-size: 16px;
-  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
-  color: #2c3e50;
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-}
-
-aside a {
-  color: #337ab7;
-  cursor: pointer;
-}
-
-aside a:hover {
-  color: #20a0ff;
-}
-
-.app-container {
-  padding: 20px;
-}
-
-.components-container {
-  margin: 30px 50px;
-  position: relative;
-}
-
-.pagination-container {
-  margin-top: 30px;
-}
-
-.text-center {
-  text-align: center;
-}
-
-.sub-navbar {
-  height: 50px;
-  line-height: 50px;
-  position: relative;
-  width: 100%;
-  text-align: right;
-  padding-right: 20px;
-  transition: 600ms ease position;
-  background: linear-gradient(90deg, #20b6f9 0%, #20b6f9 0%, #2178f1 100%, #2178f1 100%);
-}
-
-.sub-navbar .subtitle {
-  font-size: 20px;
-  color: #fff;
-}
-
-.sub-navbar.draft {
-  background: #d0d0d0;
-}
-
-.sub-navbar.deleted {
-  background: #d0d0d0;
-}
-
-.link-type,
-.link-type:focus {
-  color: #337ab7;
-  cursor: pointer;
-}
-
-.link-type:hover,
-.link-type:focus:hover {
-  color: #20a0ff;
-}
-
-.filter-container {
-  padding-bottom: 10px;
-}
-
-.filter-container .filter-item {
-  display: inline-block;
-  vertical-align: middle;
-  margin-bottom: 10px;
-}
-
-.multiselect {
-  line-height: 16px;
-}
-
-.multiselect--active {
-  z-index: 1000 !important;
-}
-
-.status.success {
-  color: #67C23A;
-}
-
-.status.danger {
-  color: #F56C6C;
-}
-
-.status.warning {
-  color: #E6A23C;
-}
-
-.hidden .el-upload {
-  display: none !important;
-}
-
-.tableHeader th {
-  background-color: #f7f7f7 !important;
-}
-
-.el-drawer__header {
-  margin-bottom: 0 !important;
-}
-
-.table-cell .cell {
-  overflow: visible !important;
-}
-
-.table-cell .cell .el-badge {
-  vertical-align: 0;
-}
-
-.el-drawer header span {
-  outline: none;
-}
-
-.el-drawer button {
-  outline: none !important;
-}
-
-.reason {
-  cursor: pointer;
-}

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
src/styles/index.min.css


+ 9 - 5
src/styles/index.scss

@@ -186,13 +186,14 @@ aside {
 // 状态颜色
 .status {
   &.success {
-    color: #67c23a;
+    color: #409eff;
   }
   &.danger {
     color: #f56c6c;
+    cursor: help;
   }
   &.warning {
-    color: #e6a23c;
+    color: #606266;
   }
 }
 
@@ -208,9 +209,6 @@ aside {
   }
 }
 
-// .el-badge__content.is-fixed{
-//   top: 14px !important;
-// }
 .el-drawer__header {
   margin-bottom: 0 !important;
 }
@@ -309,6 +307,7 @@ aside {
     > span {
       margin-right: 10px;
       font-size: 14px;
+      color: #606266;
     }
     > .el-input,
     > .el-select {
@@ -351,3 +350,8 @@ aside {
     margin-top: 0 !important;
   }
 }
+
+.form-label-tip {
+  font-size: 14px;
+  color: #999;
+}

+ 0 - 0
src/utils/format-routes-to-modules.js


+ 0 - 75
src/utils/formatRoutesToModule.js

@@ -1,75 +0,0 @@
-import { constantRoutes, asyncRoutes } from '@/router/index'
-import store from '@/store'
-import routerMap from '@/router/router-map'
-
-let routesTree = []
-let routes = []
-let routeMap = []
-
-// 获取全部路由信息
-function getRoutes() {
-  routes = [...constantRoutes, ...asyncRoutes].filter(item => item.meta)
-  if (!store.getters.roles.includes('admin')) {
-    routes = routes.filter(route => !route.meta.roles || route.meta.roles.includes('normal'))
-  }
-  return routes
-}
-
-// 从路由map中获取id
-function getRouteKeyFromMap(name, flag = false) {
-  if (flag) {
-    return routerMap.reduce((prev, item) => {
-      prev.push(...item.children)
-      return prev
-    }, []).find(item => item.name === name)?.id
-  } else {
-    return routerMap.find(item => item.name === name)?.id
-  }
-}
-
-function formatRoutesToModule() {
-  routes = getRoutes()
-  routesTree = []
-  routeMap = []
-  routes.forEach(first => {
-    const obj = {
-      label: first.meta.title,
-      value: getRouteKeyFromMap(first.meta.title, false)
-    }
-    // 提取当前登录用户可以看到的路由
-    const find = routerMap.find(item => item.name === first.meta.title)
-    if (find) {
-      routeMap.push(find)
-    }
-    if (first.children) {
-      obj.children = []
-      first.children.forEach(second => {
-        obj.children.push({
-          label: second.meta.title,
-          value: getRouteKeyFromMap(second.meta.title, true)
-        })
-      })
-    }
-    routesTree.push(obj)
-  })
-  return routesTree
-}
-
-export function getToutesTree() {
-  return formatRoutesToModule()
-}
-
-// 根据id获取栏目
-export function getModuleType(ids) {
-  ids = ids.split('-')
-  console.log(routeMap)
-  const parent = routeMap.find(item => {
-    console.log(item)
-    return item.id === parseInt(ids[0])
-  })
-  const children = parent && parent.children.find(item => item.id === parseInt(ids[1]))
-  if (!parent || !children) {
-    return store.getters.roles.includes('admin') ? '未知模块' : ''
-  }
-  return `${parent.name}/${children.name}`
-}

+ 15 - 0
src/utils/index.js

@@ -224,6 +224,21 @@ export function objectMerge(target, source) {
   return target
 }
 
+/**
+ * Merges one object to another object
+ * @param {Object} target
+ * @param {(Object)} source
+ * @returns {Object}
+ */
+export function objectCover(target, source) {
+  for (const key in source) {
+    if (Object.hasOwnProperty.call(target, key)) {
+      target[key] = source[key]
+    }
+  }
+  return target
+}
+
 /**
  * @param {HTMLElement} element
  * @param {string} className

+ 0 - 3
src/utils/open-window.js

@@ -14,9 +14,6 @@ export default function openWindow(url, strWindowName, title, w, h) {
 
   const width = w || screen.availWidth - 40
   const height = h || screen.availHeight - 50
-  // const newWindow = window.open(url, title, 'height=' + (screen.availHeight - 50) + ',width=' + (screen.availWidth - 10) + ',top=0,left=0,toolbar=no,menubar=no,scrollbars=auto,resizeable=no,location=no,status=no')
-  // const left = ((width / 2) - (w / 2)) + dualScreenLeft
-  // const top = ((height / 2) - (h / 2)) + dualScreenTop
   const left = (screen.availWidth - width) / 2
   const top = (screen.availHeight - height) / 2
 

+ 1 - 15
src/views/admin/audit/club/device/index.vue

@@ -40,19 +40,7 @@
       <el-table-column prop="snCode" label="设备SN码" align="center" />
       <el-table-column label="审核状态" width="120px" align="center">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.auditStatus === 2" size="small" type="warning">待审核</el-tag>
-          <el-tag v-if="row.auditStatus === 1" size="small" type="success">审核通过</el-tag>
-          <!-- 未通过原因展示 -->
-          <template v-if="row.auditStatus === 0">
-            <!-- <span class="status danger">审核未通过&nbsp;</span> -->
-            <el-popover placement="top-start" title="审核说明" width="400" trigger="hover" :content="row.invalidReason">
-              <el-tag slot="reference" size="small" type="danger" class="reason">
-                <span>审核未通过</span>
-                <span class="el-icon-question status danger " />
-              </el-tag>
-            </el-popover>
-            <!-- 未通过原因展示END -->
-          </template>
+          <audit-status :status="row.auditStatus" :reason="row.invalidReason" />
         </template>
       </el-table-column>
       <el-table-column label="审核时间" width="160px" align="center">
@@ -72,7 +60,6 @@
           <el-button
             v-if="row.auditStatus !== 1"
             type="primary"
-            icon="el-icon-s-check"
             size="mini"
             @click="$_navigationTo(`/audit/club/device-detail?id=${row.productId}&authId=${listQuery.authId}`)"
           >审核</el-button>
@@ -83,7 +70,6 @@
     <!-- 表格区域END -->
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 4 - 6
src/views/admin/audit/club/index.vue

@@ -58,16 +58,15 @@
       <el-table-column prop="linkMan" label="联系人" width="200px" align="center" />
       <el-table-column label="审核状态" width="120px" align="center">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.lowerAuditStatus === 0" size="small" type="danger">未完成审核</el-tag>
-          <el-tag v-if="row.lowerAuditStatus === 1" size="small" type="success">已完成审核</el-tag>
+          <span v-if="row.lowerAuditStatus === 0" class="status warning">未完成审核</span>
+          <span v-if="row.lowerAuditStatus === 1" class="status success">已完成审核</span>
         </template>
       </el-table-column>
-      <el-table-column label="操作" width="240px" align="center">
+      <el-table-column label="操作" width="160px" align="center">
         <template slot-scope="{ row }">
           <el-badge :hidden="row.lowerAuditStatus === 1" :value="row.waitAuditNum" :max="99">
             <el-button
               type="primary"
-              icon="el-icon-s-check"
               size="mini"
               @click="$_navigationTo(`/audit/club/club-list?authUserId=${row.authUserId}`)"
             >机构认证审核</el-button>
@@ -78,7 +77,6 @@
     <!-- 表格区域END -->
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"
@@ -120,7 +118,7 @@ export default {
     getList() {
       this.listLoading = true
       fetchSupplierList(this.listQuery)
-        .then(res => {
+        .then((res) => {
           if (res.code !== 0) return
           this.list = res.data.list
           this.total = res.data.total

+ 27 - 26
src/views/admin/audit/club/list.vue

@@ -43,25 +43,13 @@
       <el-table-column prop="authParty" label="机构名称" align="center" />
       <el-table-column label="审核状态" width="120px" align="center">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.auditStatus === 2" size="small" type="warning">待审核</el-tag>
-          <el-tag v-if="row.auditStatus === 1" size="small" type="success">审核通过</el-tag>
-          <!-- 未通过原因展示 -->
-          <template v-if="row.auditStatus === 0">
-            <!-- <span class="status danger">审核未通过&nbsp;</span> -->
-            <el-popover placement="top-start" title="审核说明" width="400" trigger="hover" :content="row.invalidReason">
-              <el-tag slot="reference" size="small" type="danger" class="reason">
-                <span>审核未通过</span>
-                <span class="el-icon-question status danger" />
-              </el-tag>
-            </el-popover>
-            <!-- 未通过原因展示END -->
-          </template>
+          <audit-status :status="row.auditStatus" :reason="row.invalidReason" />
         </template>
       </el-table-column>
       <el-table-column label="商品信息审核状态" width="160px" align="center">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.lowerAuditStatus === 0" size="small" type="danger">未完成审核</el-tag>
-          <el-tag v-if="row.lowerAuditStatus === 1" size="small" type="success">已完成审核</el-tag>
+          <span v-if="row.lowerAuditStatus === 0" class="status warning">未完成审核</span>
+          <span v-if="row.lowerAuditStatus === 1" class="status success">已完成审核</span>
         </template>
       </el-table-column>
 
@@ -79,19 +67,18 @@
         </template>
       </el-table-column>
 
-      <el-table-column label="操作" width="240px" align="center">
+      <el-table-column label="操作" width="280px" align="center">
         <template slot-scope="{ row }">
+          <!-- <audit-button-group type="result" :is-dot="true" :margin-right="true" @click="onClick(row, $event)" /> -->
           <el-button
             v-if="row.auditStatus !== 1"
             type="warning"
             size="mini"
-            style="margin-right: 5px"
-            icon="el-icon-s-check"
+            style="margin-right: 12px"
             @click="$_navigationTo(`/audit/club/club-detail?authId=${row.authId}`)"
           >审核</el-button>
           <el-badge :hidden="row.lowerAuditStatus === 1" :value="row.waitAuditNum" :max="99">
             <el-button
-              icon="el-icon-s-shop"
               type="primary"
               size="mini"
               @click="$_navigationTo(`/audit/club/device/list?authId=${row.authId}`)"
@@ -102,13 +89,7 @@
     </el-table>
     <!-- 表格区域END -->
     <!-- 页码 -->
-    <pagination
-      v-show="total > 0"
-      :total="total"
-      :page.sync="listQuery.pageNum"
-      :limit.sync="listQuery.pageSize"
-      @pagination="getList"
-    />
+    <pagination :total="total" :page.sync="listQuery.pageNum" :limit.sync="listQuery.pageSize" @pagination="getList" />
     <!-- 审核弹窗 -->
     <el-dialog title="授权机构审核" :visible.sync="dialogVisible" width="450px" @close="dialogClosed">
       <div class="auth-info">
@@ -185,6 +166,26 @@ export default {
   },
   methods: {
     ...mapMutations({ setMessageState: 'webSocket/SET_MESSAGE_STATE' }),
+
+    // 按钮组点击事件
+    onClick(row, type) {
+      const actions = {
+        review: this.onReview,
+        result: this.onResult,
+        audit: this.onAudit
+      }
+      actions[type](row)
+    },
+
+    // 预览
+    onReview(row) {},
+    // 驳回
+    onResult(row) {},
+    // 审核
+    onAudit(row) {
+      this.$router.push(`/audit/club/club-detail?authId=${row.authId}`)
+    },
+
     // 获取授权列表
     getList() {
       this.listLoading = true

+ 20 - 4
src/views/admin/audit/club/review.vue

@@ -21,7 +21,7 @@
         <div class="row">
           <div class="col">所在位置:</div>
           <div class="col">
-            <div class="map" @click="dialogMapVisible = true">
+            <div class="map" @click="initMap">
               <i class="el-icon-map-location" />
               <span>点击查看</span>
             </div>
@@ -137,18 +137,21 @@
     <!-- 地图坐标拾取 -->
     <el-dialog class="map-dialog" title="地图信息" :visible.sync="dialogMapVisible" width="80%">
       <!-- <location v-if="dialogMapVisible" :init-point="formData.point" @point="handlePointChange" /> -->
-      <map-ui :init-point="clubInfo.lngAndLat" />
+      <!-- <map-ui :init-point="clubInfo.lngAndLat" /> -->
+      <a-map ref="aMap" :lnglat="lnglat" />
     </el-dialog>
   </div>
 </template>
 
 <script>
 import AMapUI from '@/components/AMapUI'
+import SimpleAMap from '@/components/SimpleAMap'
 import { getAuthFormData, auditAuth } from '@/api/auth'
 import { mapGetters } from 'vuex'
 export default {
   components: {
-    [AMapUI.name]: AMapUI
+    [AMapUI.name]: AMapUI,
+    [SimpleAMap.name]: SimpleAMap
   },
   data() {
     return {
@@ -204,13 +207,26 @@ export default {
     }
   },
   computed: {
-    ...mapGetters(['authUserId'])
+    ...mapGetters(['authUserId']),
+    // 位置坐标
+    lnglat() {
+      return this.clubInfo.lngAndLat ? this.clubInfo.lngAndLat.split(',') : null
+    }
   },
   created() {
     this.auditForm.authId = this.$route.query.authId
     this.getDetail()
   },
   methods: {
+    // 地图定位
+    initMap() {
+      this.dialogMapVisible = true
+      if (this.lnglat) {
+        this.$nextTick(() => {
+          this.$refs.aMap.init()
+        })
+      }
+    },
     // 数据回显
     getDetail() {
       getAuthFormData({ authId: this.auditForm.authId }).then((res) => {

+ 3 - 5
src/views/admin/audit/device/index.vue

@@ -58,16 +58,15 @@
       <el-table-column prop="linkMan" label="联系人" width="200px" align="center" />
       <el-table-column label="审核状态" width="220px" align="center">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.lowerAuditStatus === 0" size="small" type="danger">未完成审核</el-tag>
-          <el-tag v-if="row.lowerAuditStatus === 1" size="small" type="success">已完成审核</el-tag>
+          <span v-if="row.lowerAuditStatus === 0" class="status warning">未完成审核</span>
+          <span v-if="row.lowerAuditStatus === 1" class="status success">已完成审核</span>
         </template>
       </el-table-column>
-      <el-table-column label="操作" width="240px" align="center">
+      <el-table-column label="操作" width="160px" align="center">
         <template slot-scope="{ row }">
           <el-badge :hidden="row.lowerAuditStatus === 1" :value="row.productTypeWaitNum" :max="99">
             <el-button
               type="primary"
-              icon="el-icon-s-check"
               size="mini"
               @click="$_navigationTo(`/audit/device/device-list?authUserId=${row.authUserId}`)"
             >设备分类审核</el-button>
@@ -78,7 +77,6 @@
     <!-- 表格区域END -->
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 7 - 35
src/views/admin/audit/device/list.vue

@@ -32,19 +32,7 @@
       <el-table-column prop="name" label="设备名称" align="center" />
       <el-table-column label="审核状态" width="220px" align="center">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.auditStatus === 2" size="small" type="warning">待审核</el-tag>
-          <el-tag v-if="row.auditStatus === 1" size="small" type="success">审核通过</el-tag>
-          <!-- 未通过原因展示 -->
-          <template v-if="row.auditStatus === 0">
-            <!-- <span class="status danger">审核未通过&nbsp;</span> -->
-            <el-popover placement="top-start" title="审核说明" width="400" trigger="hover" :content="row.invalidReason">
-              <el-tag slot="reference" size="small" type="danger" class="reason">
-                <span>审核未通过</span>
-                <span class="el-icon-question status danger " />
-              </el-tag>
-            </el-popover>
-            <!-- 未通过原因展示END -->
-          </template>
+          <audit-status :status="row.auditStatus" :reason="row.invalidReason" />
         </template>
       </el-table-column>
       <el-table-column label="审核时间" width="250px" align="center">
@@ -61,36 +49,20 @@
       </el-table-column>
       <el-table-column label="操作" width="240px" align="center">
         <template slot-scope="{ row }">
-          <el-button
-            v-if="row.auditStatus !== 1"
-            type="warning"
-            size="mini"
-            style="margin-right:5px"
-            icon="el-icon-s-check"
-            @click="handleAudit(row)"
-          >审核</el-button>
+          <el-button v-if="row.auditStatus !== 1" type="warning" size="mini" @click="handleAudit(row)">审核</el-button>
           <span v-else class="status success el-icon-check">&nbsp;已审核</span>
         </template>
       </el-table-column>
     </el-table>
 
     <!-- 审核对话框 -->
-    <el-dialog
-      title="审核"
-      :visible.sync="dialogVisible"
-      width="30%"
-      @closed="onDialogClose"
-    >
+    <el-dialog title="审核" :visible.sync="dialogVisible" width="30%" @closed="onDialogClose">
       <el-form label-width="80px">
         <el-form-item label="设备名称:">
           <span v-text="currentData.name" />
         </el-form-item>
         <el-form-item label="设备图片:">
-          <el-image
-            style="width: 200px; height: 200px"
-            :src="currentData.image"
-            :preview-src-list="srcList"
-          />
+          <el-image style="width: 200px; height: 200px" :src="currentData.image" :preview-src-list="srcList" />
         </el-form-item>
         <el-form-item label="审核状态:">
           <el-radio-group v-model="dialogData.auditStatus">
@@ -190,9 +162,9 @@ export default {
 </script>
 
 <style scoped lang="scss">
-.app-container{
-  ::v-deep{
-    .el-dialog__body{
+.app-container {
+  ::v-deep {
+    .el-dialog__body {
       padding-bottom: 0;
     }
   }

+ 8 - 19
src/views/admin/audit/material/article/index.vue

@@ -34,23 +34,15 @@
       <el-table-column label="序号" :index="indexMethod" type="index" width="80" align="center" />
       <el-table-column label="文章标题" prop="articleTitle" align="center" />
       <el-table-column label="文章头图" width="80px" align="center">
-        <template slot-scope="{ row }"> <el-image style="width: 50px; height: 50px" :src="row.articleImage" /></template>
+        <template slot-scope="{ row }">
+          <el-image
+            style="width: 50px; height: 50px"
+            :src="row.articleImage"
+          /></template>
       </el-table-column>
       <el-table-column label="审核状态" width="120px" align="center">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.auditStatus === 2" size="small" type="warning">待审核</el-tag>
-          <el-tag v-if="row.auditStatus === 1" size="small" type="success">审核通过</el-tag>
-          <!-- 未通过原因展示 -->
-          <template v-if="row.auditStatus === 0">
-            <!-- <span class="status danger">审核未通过&nbsp;</span> -->
-            <el-popover placement="top-start" title="审核说明" width="400" trigger="hover" :content="row.invalidReason">
-              <el-tag slot="reference" size="small" type="danger" class="reason">
-                <span>审核未通过</span>
-                <span class="el-icon-question status danger " />
-              </el-tag>
-            </el-popover>
-            <!-- 未通过原因展示END -->
-          </template>
+          <audit-status :status="row.auditStatus" :reason="row.invalidReason" />
         </template>
       </el-table-column>
       <el-table-column label="审核时间" width="160px" align="center">
@@ -72,8 +64,6 @@
             v-if="row.auditStatus !== 1"
             type="primary"
             size="mini"
-            style="margin-right:5px"
-            icon="el-icon-s-check"
             @click="$_navigationTo(`/audit/material/article-detail?articleId=${row.articleId}`)"
           >审核</el-button>
           <span v-else class="status success el-icon-check">&nbsp;已审核</span>
@@ -83,7 +73,6 @@
     <!-- 表格区域END -->
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"
@@ -122,7 +111,7 @@ export default {
     getList() {
       this.listLoading = true
       getArticleList(this.listQuery)
-        .then(res => {
+        .then((res) => {
           if (res.code !== 0) return
           this.list = res.data.list
           this.total = res.data.total
@@ -134,7 +123,7 @@ export default {
     },
     // 初始化预览图片列表
     initPreviewList(list) {
-      list.forEach(item => this.srcList.push(item.articleCover))
+      list.forEach((item) => this.srcList.push(item.articleCover))
     },
     indexMethod(index) {
       return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1

+ 2 - 22
src/views/admin/audit/material/file/index.vue

@@ -44,25 +44,7 @@
       <el-table-column label="文件名称" prop="fileTitle" align="center" />
       <el-table-column label="审核状态" width="120px" align="center">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.auditStatus === 2" size="small" type="warning">待审核</el-tag>
-          <el-tag v-if="row.auditStatus === 1" size="small" type="success">审核通过</el-tag>
-          <!-- 未通过原因展示 -->
-          <template v-if="row.auditStatus === 0">
-            <!-- <span class="status danger">审核未通过&nbsp;</span> -->
-            <el-popover
-              placement="top-start"
-              title="审核说明"
-              width="400"
-              trigger="hover"
-              :content="row.invalidReason"
-            >
-              <el-tag slot="reference" size="small" type="danger" class="reason">
-                <span>审核未通过</span>
-                <span class="el-icon-question status danger " />
-              </el-tag>
-            </el-popover>
-            <!-- 未通过原因展示END -->
-          </template>
+          <audit-status :status="row.auditStatus" :reason="row.invalidReason" />
         </template>
       </el-table-column>
       <el-table-column label="审核时间" width="160px" align="center">
@@ -84,8 +66,6 @@
             v-if="row.auditStatus===2"
             type="primary"
             size="mini"
-            style="margin-right:5px"
-            icon="el-icon-s-check"
             @click="handleShowDialog(row)"
           >审核</el-button>
           <span v-else class="status success el-icon-check">&nbsp;已审核</span>
@@ -94,7 +74,7 @@
     </el-table>
     <!-- 表格区域END -->
     <!-- 页码 -->
-    <pagination v-show="total > 0" :total="total" :page.sync="listQuery.pageNum" :limit.sync="listQuery.pageSize" @pagination="getList(listQuery)" />
+    <pagination :total="total" :page.sync="listQuery.pageNum" :limit.sync="listQuery.pageSize" @pagination="getList(listQuery)" />
     <!-- 视频预览对话框 -->
     <el-dialog
       title="视频审核"

+ 1 - 16
src/views/admin/audit/material/image/index.vue

@@ -35,19 +35,7 @@
       <el-table-column label="图片标题" prop="imageTitle" align="center" />
       <el-table-column label="审核状态" width="120px" align="center">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.auditStatus === 2" size="small" type="warning">待审核</el-tag>
-          <el-tag v-if="row.auditStatus === 1" size="small" type="success">审核通过</el-tag>
-          <!-- 未通过原因展示 -->
-          <template v-if="row.auditStatus === 0">
-            <!-- <span class="status danger">审核未通过&nbsp;</span> -->
-            <el-popover placement="top-start" title="审核说明" width="400" trigger="hover" :content="row.invalidReason">
-              <el-tag slot="reference" size="small" type="danger" class="reason">
-                <span>审核未通过</span>
-                <span class="el-icon-question status danger " />
-              </el-tag>
-            </el-popover>
-            <!-- 未通过原因展示END -->
-          </template>
+          <audit-status :status="row.auditStatus" :reason="row.invalidReason" />
         </template>
       </el-table-column>
       <el-table-column label="审核时间" width="160px" align="center">
@@ -69,8 +57,6 @@
             v-if="row.auditStatus !== 1"
             type="primary"
             size="mini"
-            style="margin-right:5px"
-            icon="el-icon-s-check"
             @click="$_navigationTo(`/audit/material/image-detail?imageId=${row.imageId}`)"
           >审核</el-button>
           <span v-else class="status success el-icon-check">&nbsp;已审核</span>
@@ -80,7 +66,6 @@
     <!-- 表格区域END -->
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 13 - 35
src/views/admin/audit/material/index.vue

@@ -58,51 +58,26 @@
       <el-table-column prop="linkMan" label="联系人" width="200px" align="center" />
       <el-table-column label="审核状态" width="150px" align="center">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.lowerAuditStatus === 0" size="small" type="danger">未完成审核</el-tag>
-          <el-tag v-if="row.lowerAuditStatus === 1" size="small" type="success">已完成审核</el-tag>
+          <span v-if="row.lowerAuditStatus === 0" class="status warning">未完成审核</span>
+          <span v-if="row.lowerAuditStatus === 1" class="status success">已完成审核</span>
         </template>
       </el-table-column>
-      <el-table-column label="待审核" width="460px" align="center">
+      <el-table-column label="待审核" width="390px" align="center">
         <template slot-scope="{ row }">
           <el-badge :hidden="row.articleWaitNum === 0" :value="row.articleWaitNum" :max="99">
-            <el-button
-              type="primary"
-              icon="el-icon-tickets"
-              size="mini"
-              @click="$_navigationTo(`material/article-list?authUserId=${row.authUserId}`)"
-            >文章</el-button>
+            <el-button type="primary" size="mini" @click="goAuditList(row, 'article')">文章</el-button>
           </el-badge>
           <el-badge :hidden="row.imageWaitNum === 0" :value="row.imageWaitNum" :max="99">
-            <el-button
-              type="primary"
-              icon="el-icon-picture-outline"
-              size="mini"
-              @click="$_navigationTo(`material/image-list?authUserId=${row.authUserId}`)"
-            >图片</el-button>
+            <el-button type="primary" size="mini" @click="goAuditList(row, 'image')">图片</el-button>
           </el-badge>
           <el-badge :hidden="row.videoWaitNum === 0" :value="row.videoWaitNum" :max="99">
-            <el-button
-              type="primary"
-              icon="el-icon-video-camera"
-              size="mini"
-              @click="$_navigationTo(`material/video-list?authUserId=${row.authUserId}`)"
-            >视频</el-button>
+            <el-button type="primary" size="mini" @click="goAuditList(row, 'video')">视频</el-button>
           </el-badge>
           <el-badge :hidden="row.fileWaitNum === 0" :value="row.fileWaitNum" :max="99">
-            <el-button
-              type="primary"
-              icon="el-icon-document-copy"
-              size="mini"
-              @click="$_navigationTo(`material/file-list?authUserId=${row.authUserId}`)"
-            >文件</el-button>
+            <el-button type="primary" size="mini" @click="goAuditList(row, 'file')">文件</el-button>
           </el-badge>
           <el-badge :hidden="row.zipWaitNum === 0" :value="row.zipWaitNum" :max="99">
-            <el-button
-              type="primary"
-              icon="el-icon-document-copy"
-              size="mini"
-              @click="$_navigationTo(`material/package-list?authUserId=${row.authUserId}`)"
-            >资料包</el-button>
+            <el-button type="primary" size="mini" @click="goAuditList(row, 'package')">资料包</el-button>
           </el-badge>
         </template>
       </el-table-column>
@@ -110,7 +85,6 @@
     <!-- 表格区域END -->
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"
@@ -146,11 +120,15 @@ export default {
     this.getList()
   },
   methods: {
+    goAuditList(row, type) {
+      const url = `material/${type}-list?authUserId=${row.authUserId}`
+      this.$router.push(url)
+    },
     // 获取供应商待审核列表数据
     getList() {
       this.listLoading = true
       fetchSupplierList(this.listQuery)
-        .then(res => {
+        .then((res) => {
           if (res.code !== 0) return
           this.list = res.data.list
           this.total = res.data.total

+ 2 - 22
src/views/admin/audit/material/package/index.vue

@@ -44,25 +44,7 @@
       <el-table-column label="文件名称" prop="fileTitle" align="center" />
       <el-table-column label="审核状态" width="120px" align="center">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.auditStatus === 2" size="small" type="warning">待审核</el-tag>
-          <el-tag v-if="row.auditStatus === 1" size="small" type="success">审核通过</el-tag>
-          <!-- 未通过原因展示 -->
-          <template v-if="row.auditStatus === 0">
-            <!-- <span class="status danger">审核未通过&nbsp;</span> -->
-            <el-popover
-              placement="top-start"
-              title="审核说明"
-              width="400"
-              trigger="hover"
-              :content="row.invalidReason"
-            >
-              <el-tag slot="reference" size="small" type="danger" class="reason">
-                <span>审核未通过</span>
-                <span class="el-icon-question status danger " />
-              </el-tag>
-            </el-popover>
-            <!-- 未通过原因展示END -->
-          </template>
+          <audit-status :status="row.auditStatus" :reason="row.invalidReason" />
         </template>
       </el-table-column>
       <el-table-column label="审核时间" width="160px" align="center">
@@ -84,8 +66,6 @@
             v-if="row.auditStatus===2"
             type="primary"
             size="mini"
-            style="margin-right:5px"
-            icon="el-icon-s-check"
             @click="handleShowDialog(row)"
           >审核</el-button>
           <span v-else class="status success el-icon-check">&nbsp;已审核</span>
@@ -94,7 +74,7 @@
     </el-table>
     <!-- 表格区域END -->
     <!-- 页码 -->
-    <pagination v-show="total > 0" :total="total" :page.sync="listQuery.pageNum" :limit.sync="listQuery.pageSize" @pagination="getList(listQuery)" />
+    <pagination :total="total" :page.sync="listQuery.pageNum" :limit.sync="listQuery.pageSize" @pagination="getList(listQuery)" />
     <!-- 视频预览对话框 -->
     <el-dialog
       title="视频审核"

+ 1 - 16
src/views/admin/audit/material/video/index.vue

@@ -35,19 +35,7 @@
       <el-table-column label="视频名称" prop="videoTitle" align="center" />
       <el-table-column label="审核状态" width="120px" align="center">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.auditStatus === 2" size="small" type="warning">待审核</el-tag>
-          <el-tag v-if="row.auditStatus === 1" size="small" type="success">审核通过</el-tag>
-          <!-- 未通过原因展示 -->
-          <template v-if="row.auditStatus === 0">
-            <!-- <span class="status danger">审核未通过&nbsp;</span> -->
-            <el-popover placement="top-start" title="审核说明" width="400" trigger="hover" :content="row.invalidReason">
-              <el-tag slot="reference" size="small" type="danger" class="reason">
-                <span>审核未通过</span>
-                <span class="el-icon-question status danger" />
-              </el-tag>
-            </el-popover>
-            <!-- 未通过原因展示END -->
-          </template>
+          <audit-status :status="row.auditStatus" :reason="row.invalidReason" />
         </template>
       </el-table-column>
       <el-table-column label="审核时间" width="160px" align="center">
@@ -69,8 +57,6 @@
             v-if="row.auditStatus !== 1"
             type="primary"
             size="mini"
-            style="margin-right: 5px"
-            icon="el-icon-s-check"
             @click="handleShowDialog(row)"
           >审核</el-button>
           <span v-else class="status success el-icon-check">&nbsp;已审核</span>
@@ -80,7 +66,6 @@
     <!-- 表格区域END -->
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 10 - 19
src/views/admin/audit/personnel/index.vue

@@ -58,27 +58,17 @@
       <el-table-column prop="linkMan" label="联系人" width="200px" align="center" />
       <el-table-column label="审核状态" width="220px" align="center">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.lowerAuditStatus === 0" size="small" type="danger">未完成审核</el-tag>
-          <el-tag v-if="row.lowerAuditStatus === 1" size="small" type="success">已完成审核</el-tag>
+          <span v-if="row.lowerAuditStatus === 0" class="status warning">未完成审核</span>
+          <span v-if="row.lowerAuditStatus === 1" class="status success">已完成审核</span>
         </template>
       </el-table-column>
-      <el-table-column label="操作" width="320px" align="center">
+      <el-table-column label="操作" width="260px" align="center">
         <template slot-scope="{ row }">
           <el-badge :hidden="row.lowerAuditStatus === 1" :value="row.doctorWaitNum" :max="99">
-            <el-button
-              type="primary"
-              icon="el-icon-s-check"
-              size="mini"
-              @click="$_navigationTo(`personnel/operate/doctor-list?authUserId=${row.authUserId}`)"
-            >操作师审核</el-button>
+            <el-button type="primary" size="mini" @click="goAuditList(row, 'operate')">操作师审核</el-button>
           </el-badge>
           <el-badge :hidden="row.lowerAuditStatus === 1" :value="row.doctorWaitNum" :max="99">
-            <el-button
-              type="primary"
-              icon="el-icon-s-check"
-              size="mini"
-              @click="$_navigationTo(`personnel/training/doctor-list?authUserId=${row.authUserId}`)"
-            >培训师审核</el-button>
+            <el-button type="primary" size="mini" @click="goAuditList(row, 'training')">培训师审核</el-button>
           </el-badge>
         </template>
       </el-table-column>
@@ -86,7 +76,6 @@
     <!-- 表格区域END -->
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"
@@ -122,13 +111,15 @@ export default {
     this.getList()
   },
   methods: {
-    // 过滤列表
-    handleFilter() {},
+    goAuditList(row, type) {
+      const url = `personnel/${type}/doctor-list?authUserId=${row.authUserId}`
+      this.$router.push(url)
+    },
     // 获取供应商列表
     getList() {
       this.listLoading = true
       fetchSupplierList(this.listQuery)
-        .then(res => {
+        .then((res) => {
           if (res.code !== 0) return
           this.list = res.data.list
           this.total = res.data.total

+ 1 - 14
src/views/admin/audit/personnel/operate/index.vue

@@ -39,19 +39,7 @@
 
       <el-table-column label="审核状态" width="120px" align="center">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.auditStatus === 2" size="small" type="warning">待审核</el-tag>
-          <el-tag v-if="row.auditStatus === 1" size="small" type="success">审核通过</el-tag>
-          <!-- 未通过原因展示 -->
-          <template v-if="row.auditStatus === 0">
-            <!-- <span class="status danger">审核未通过&nbsp;</span> -->
-            <el-popover placement="top-start" title="审核说明" width="400" trigger="hover" :content="row.invalidReason">
-              <el-tag slot="reference" size="small" type="danger" class="reason">
-                <span>审核未通过</span>
-                <span class="el-icon-question status danger " />
-              </el-tag>
-            </el-popover>
-            <!-- 未通过原因展示END -->
-          </template>
+          <audit-status :status="row.auditStatus" :reason="row.invalidReason" />
         </template>
       </el-table-column>
 
@@ -86,7 +74,6 @@
     </el-table>
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 1 - 14
src/views/admin/audit/personnel/training/index.vue

@@ -39,19 +39,7 @@
 
       <el-table-column label="审核状态" width="120px" align="center">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.auditStatus === 2" size="small" type="warning">待审核</el-tag>
-          <el-tag v-if="row.auditStatus === 1" size="small" type="success">审核通过</el-tag>
-          <!-- 未通过原因展示 -->
-          <template v-if="row.auditStatus === 0">
-            <!-- <span class="status danger">审核未通过&nbsp;</span> -->
-            <el-popover placement="top-start" title="审核说明" width="400" trigger="hover" :content="row.invalidReason">
-              <el-tag slot="reference" size="small" type="danger" class="reason">
-                <span>审核未通过</span>
-                <span class="el-icon-question status danger " />
-              </el-tag>
-            </el-popover>
-            <!-- 未通过原因展示END -->
-          </template>
+          <audit-status :status="row.auditStatus" :reason="row.invalidReason" />
         </template>
       </el-table-column>
 
@@ -86,7 +74,6 @@
     </el-table>
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 27 - 4
src/views/admin/logistics-licensed/club/detail.vue

@@ -21,7 +21,7 @@
         <div class="row">
           <div class="col">所在位置:</div>
           <div class="col">
-            <div class="map" @click="dialogMapVisible = true">
+            <div class="map" @click="initMap">
               <i class="el-icon-map-location" />
               <span>点击查看</span>
             </div>
@@ -31,7 +31,12 @@
       <div class="row">
         <div class="col">logo:</div>
         <div class="col">
-          <el-image v-if="clubInfo.logo" style="width: 120px; height: 120px" :src="clubInfo.logo" :preview-src-list="[clubInfo.logo]" />
+          <el-image
+            v-if="clubInfo.logo"
+            style="width: 120px; height: 120px"
+            :src="clubInfo.logo"
+            :preview-src-list="[clubInfo.logo]"
+          />
         </div>
       </div>
       <div class="row">
@@ -132,17 +137,20 @@
     <!-- 地图坐标拾取 -->
     <el-dialog class="map-dialog" title="地图信息" :visible.sync="dialogMapVisible" width="80%">
       <!-- <location v-if="dialogMapVisible" :init-point="formData.point" @point="handlePointChange" /> -->
-      <map-ui :init-point="clubInfo.lngAndLat" />
+      <!-- <map-ui :init-point="clubInfo.lngAndLat" /> -->
+      <a-map ref="aMap" :lnglat="lnglat" />
     </el-dialog>
   </div>
 </template>
 
 <script>
 import AMapUI from '@/components/AMapUI'
+import SimpleAMap from '@/components/SimpleAMap'
 import { getAuthFormData } from '@/api/auth'
 export default {
   components: {
-    [AMapUI.name]: AMapUI
+    [AMapUI.name]: AMapUI,
+    [SimpleAMap.name]: SimpleAMap
   },
   data() {
     return {
@@ -187,11 +195,26 @@ export default {
       }
     }
   },
+  computed: {
+    // 位置坐标
+    lnglat() {
+      return this.clubInfo.lngAndLat ? this.clubInfo.lngAndLat.split(',') : null
+    }
+  },
   created() {
     this.authId = this.$route.query.id
     this.getDetail()
   },
   methods: {
+    // 地图定位
+    initMap() {
+      this.dialogMapVisible = true
+      if (this.lnglat) {
+        this.$nextTick(() => {
+          this.$refs.aMap.init()
+        })
+      }
+    },
     // 数据回显
     getDetail() {
       getAuthFormData({ authId: this.authId }).then((res) => {

+ 5 - 16
src/views/admin/logistics-licensed/club/device/index.vue

@@ -35,29 +35,18 @@
       <!-- <el-table-column v-if="false" label="创建人" width="180px" align="center" prop="createBy" /> -->
       <el-table-column label="操作" align="center" width="240px" class-name="small-padding fixed-width">
         <template slot-scope="{ row }">
-          <permission-button
-            type="default"
-            size="mini"
-            @click="$_navigationTo(`device-detail?id=${row.productId}`)"
-          >
+          <el-button type="default" size="mini" @click="$_navigationTo(`device-detail?id=${row.productId}`)">
             查看
-          </permission-button>
-          <permission-button v-if="row.auditStatus === 1" type="primary" size="mini" @click="handleShowQRcode(row)">
+          </el-button>
+          <el-button :disabled="row.auditStatus !== 1" type="primary" size="mini" @click="handleShowQRcode(row)">
             二维码
-          </permission-button>
-          <permission-button v-else type="info" size="mini" disabled> 二维码 </permission-button>
+          </el-button>
         </template>
       </el-table-column>
     </el-table>
 
     <!-- 页码 -->
-    <pagination
-      v-show="total > 0"
-      :total="total"
-      :page.sync="listQuery.pageNum"
-      :limit.sync="listQuery.pageSize"
-      @pagination="getList"
-    />
+    <pagination :total="total" :page.sync="listQuery.pageNum" :limit.sync="listQuery.pageSize" @pagination="getList" />
 
     <!-- 二维码 -->
     <transition name="fade">

+ 0 - 1
src/views/admin/logistics-licensed/components/club-list.vue

@@ -70,7 +70,6 @@
 
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 0 - 1
src/views/admin/logistics-licensed/components/supplier-list.vue

@@ -82,7 +82,6 @@
 
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 0 - 1
src/views/admin/member/index.vue

@@ -77,7 +77,6 @@
     </el-table>
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 167 - 0
src/views/admin/settings/auth-card/components/supplier-list.vue

@@ -0,0 +1,167 @@
+<template>
+  <div class="supplier-list">
+    <div class="filter-container">
+      <div class="filter-control">
+        <span>供应商名称:</span>
+        <el-input
+          v-model="listQuery.shopName"
+          size="mini"
+          placeholder="供应商名称"
+          @keyup.enter.native="filterSupplierList"
+        />
+      </div>
+      <div class="filter-control">
+        <span>供应商类型:</span>
+        <el-select
+          v-model="listQuery.shopType"
+          placeholder="供应商类型"
+          size="mini"
+          clearable
+          @change="filterSupplierList"
+        >
+          <el-option label="所有类型" value="" />
+          <el-option label="代理商" :value="2" />
+          <el-option label="品牌方" :value="1" />
+        </el-select>
+      </div>
+      <div class="filter-control">
+        <span>手机号:</span>
+        <el-input
+          v-model="listQuery.mobile"
+          size="mini"
+          placeholder="手机号"
+          @keyup.enter.native="filterSupplierList"
+        />
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" size="mini" @click="filterSupplierList">查询</el-button>
+      </div>
+    </div>
+    <el-table
+      v-infinite-scroll="onLoad"
+      :data="supplierList"
+      border
+      class="infinite-list hide-table-check-all"
+      style="overflow: auto"
+      :infinite-scroll-delay="300"
+      :infinite-scroll-immediate="false"
+      header-row-class-name="tableHeader"
+      highlight-current-row
+      @row-click="handleSelectSupplier"
+    >
+      >
+      <el-table-column label="选择" width="55" align="center">
+        <template slot-scope="{ row }">
+          <el-radio v-model="selectedAuthUserId" :label="row.authUserId"><span v-show="false">1</span></el-radio>
+        </template>
+      </el-table-column>
+      <el-table-column label="序号" type="index" width="80" align="center" />
+      <el-table-column property="name" label="供应商名称" />
+      <el-table-column label="供应商类型" align="center" width="120">
+        <template slot-scope="{ row }">
+          <span v-if="row.shopType === 1">品牌方</span>
+          <span v-else>代理商</span>
+        </template>
+      </el-table-column>
+      <!-- <el-table-column label="登录账号" align="center">
+        <template slot-scope="{ row }">
+          <span v-if="row.loginAccount">{{ row.loginAccount }}</span>
+          <span v-else>未绑定</span>
+        </template>
+      </el-table-column> -->
+      <el-table-column prop="mobile" label="手机号" align="center" width="160" />
+      <el-table-column prop="linkMan" label="联系人" align="center" />
+    </el-table>
+    <div class="control">
+      <el-button @click="onCancel">取 消</el-button>
+      <el-button type="primary" @click="onConfirm">确定</el-button>
+    </div>
+  </div>
+</template>
+<script>
+import { fetchSupplierList } from '@/api/supplier'
+import { deepClone } from '@/utils'
+export default {
+  name: 'SupplierList',
+  data() {
+    return {
+      listQuery: {
+        shopName: '',
+        shopType: '',
+        mobile: '',
+        pageNum: 1,
+        pageSize: 10
+      },
+      supplierList: [],
+      selectedAuthUserId: '',
+      selectedSupplierInfo: null
+    }
+  },
+  created() {
+    this.filterSupplierList()
+  },
+  methods: {
+    // 取消
+    onCancel() {
+      this.selectedAuthUserId = ''
+      this.selectedSupplierInfo = null
+      this.$emit('cancel', this.selectedSupplierInfo)
+    },
+    // 确认
+    onConfirm() {
+      this.$emit('confirm', deepClone(this.selectedSupplierInfo))
+      this.selectedAuthUserId = ''
+      this.selectedSupplierInfo = null
+    },
+    // 确认选中的供应商
+    handleSubmitSupplier() {
+      this.dialogTableVisible = false
+      this.currentSupplierList = [this.selectedSupplierInfo]
+    },
+    // 选择供应商
+    handleSelectSupplier(e) {
+      this.selectedAuthUserId = e.authUserId
+      this.selectedSupplierInfo = e
+    },
+    // 选择供应商对话框关闭事件
+    handleDialogClosed() {
+      this.listQuery.pageNum = 1
+      this.listQuery.shopName = ''
+      this.listQuery.shopType = ''
+      this.listQuery.mobile = ''
+      this.listQuery.linkMan = ''
+    },
+    // 筛选供应商
+    filterSupplierList() {
+      this.listQuery.pageNum = 1
+      this.supplierList = []
+      this.fetchSupplierList()
+    },
+    // 获取供应商列表
+    fetchSupplierList() {
+      fetchSupplierList(this.listQuery).then((res) => {
+        console.log(res)
+        this.supplierList = [...this.supplierList, ...res.data.list]
+        this.hasNextPage = res.data.hasNextPage
+        this.total = res.data.total
+      })
+    },
+    onLoad() {
+      if (!this.hasNextPage) return
+      this.listQuery.pageNum++
+      this.fetchSupplierList()
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.supplier-list {
+  .control {
+    text-align: right;
+    margin-top: 12px;
+  }
+  .infinite-list {
+    height: 400px;
+  }
+}
+</style>

+ 346 - 0
src/views/admin/settings/auth-card/index.vue

@@ -0,0 +1,346 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <div class="filter-control">
+        <span>所属供应商:</span>
+        <el-select
+          v-model="listQuery.authUserId"
+          placeholder="请选择供应商"
+          clearable
+          style="width: 200px"
+          class="filter-item"
+          @change="getList"
+        >
+          <template v-for="item in supplierList">
+            <el-option :key="item.authUserId" :label="item.name" :value="item.authUserId" />
+          </template>
+        </el-select>
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" @click="getList">查询</el-button>
+        <el-button type="primary" @click="addCardVisible = true">添加</el-button>
+      </div>
+    </div>
+    <el-table v-loading="listLoading" style="width: 100%" header-row-class-name="tableHeader" :data="list" border fit>
+      <el-table-column :index="indexMethod" label="序号" type="index" width="80" align="center" />
+      <el-table-column label="授权牌模板" align="center" width="200px">
+        <template slot-scope="{ row }">
+          <el-tooltip effect="dark" content="点击查看全图" placement="top-start">
+            <el-image :src="row.templateImage" :preview-src-list="[row.templateImage]" fit="cover" />
+          </el-tooltip>
+        </template>
+      </el-table-column>
+      <el-table-column prop="shopName" label="所属供应商" align="center" />
+      <el-table-column label="操作" align="center" width="320px">
+        <template slot-scope="{ row }">
+          <el-button type="primary" size="mini" @click="onChangeSupplier(row)">更换供应商</el-button>
+          <el-button type="primary" size="mini" @click="onTempEdit(row)">编辑</el-button>
+          <!-- 隐藏其一 -->
+          <el-button v-if="row.status === 0" type="info" size="mini" @click="onTempStatusChange(row)">启用</el-button>
+          <el-button v-else type="danger" size="mini" @click="onTempStatusChange(row)">停用</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 供应商列表 -->
+    <el-dialog title="选择供应商" :visible.sync="selectSupplierVisible" width="66%" @close="onSelectSupplierClose">
+      <supplier-list @cancel="selectSupplierVisible = false" @confirm="onSupplierConfirm('edit', $event)" />
+    </el-dialog>
+    <!-- 上传图片 -->
+    <el-dialog title="添加授权牌模板" :visible.sync="addCardVisible" width="40%" @closed="onAddCardClose">
+      <el-dialog width="66%" title="选择供应商" :visible.sync="addCardInnerVisible" append-to-body>
+        <supplier-list @cancel="addCardInnerVisible = false" @confirm="onSupplierConfirm('add', $event)" />
+      </el-dialog>
+      <el-form ref="addCardForm" :model="formData" label-width="120px" :rules="rules">
+        <el-form-item label="授权牌模板:" prop="templateImage">
+          <el-input v-show="false" v-model="formData.templateImage" />
+          <upload-image
+            :limit="1"
+            tip="建议尺寸:542px * 546px"
+            :image-list="tempList"
+            @success="uploadTempImageSuccess"
+            @remove="handleLogoImageRemove"
+          />
+        </el-form-item>
+        <el-form-item label="二维码位置:" prop="qrPosition">
+          <el-input
+            v-model="formData.qrPosition"
+            placeholder="请输入二维码位置坐标,以英文逗号隔开,分别为二维码左上角X,Y轴坐标(例如:100,100)"
+          />
+        </el-form-item>
+        <el-form-item label="二维码大小:" prop="qrSize">
+          <el-input v-model.number="formData.qrSize" placeholder="请输入二维码大小(例如:53)" />
+        </el-form-item>
+        <el-form-item label="LOGO大小:" prop="logoSize">
+          <el-input v-model="formData.logoSize" placeholder="请输入授权牌logo建议尺寸宽高(例如:212,98)" />
+        </el-form-item>
+        <el-form-item label="所属供应商:" prop="authUserId">
+          <el-input v-show="false" v-model="formData.authUserId" />
+          <div class="current-info">
+            <span v-if="selectSupplier" class="supplier-name">{{ selectSupplier.name }}</span>
+            <span class="supplier-change" @click="addCardInnerVisible = true">
+              {{ selectSupplier ? '更换供应商' : '选择供应商' }}
+            </span>
+          </div>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="addCardVisible = false">取 消</el-button>
+        <el-button type="primary" :loading="isLoading" @click="onConfirm">确定</el-button>
+      </div>
+    </el-dialog>
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="getList(listQuery)"
+    />
+  </div>
+</template>
+<script>
+import UploadImage from '@/components/UploadImage'
+import SupplierList from './components/supplier-list.vue'
+import { authTempSave, fetchAuthTempList } from '@/api/system'
+import { fetchSupplierList } from '@/api/supplier'
+import { objectCover } from '@/utils'
+export default {
+  components: {
+    UploadImage,
+    SupplierList
+  },
+  data() {
+    const validateQrPosition = (rule, value, callback) => {
+      if (!value) return callback()
+      if (value.split(',').length === 2) {
+        return callback()
+      }
+      callback(new Error('二维码坐标格式不正确,请改为(X坐标,Y坐标) => (100,100)'))
+    }
+
+    const validateLogoSize = (rule, value, callback) => {
+      if (!value) return callback()
+      if (value.split(',').length === 2) {
+        return callback()
+      }
+      callback(new Error('logo建议尺寸格式不正确,请改为(宽,高)格式'))
+    }
+
+    return {
+      listLoading: false,
+      isLoading: false,
+      listQuery: {
+        listType: 1,
+        authUserId: '',
+        pageSize: 15,
+        pageNum: 1
+      },
+      list: [],
+      total: 0,
+      supplierList: [],
+      formData: {
+        templateImage: '',
+        authUserId: '',
+        qrPosition: '',
+        qrSize: '',
+        logoSize: ''
+      },
+      addCardVisible: false,
+      addCardInnerVisible: false,
+      selectSupplierVisible: false,
+      selectSupplier: null,
+      // 授权牌模板列表
+      tempList: [],
+      // 需要更换供应商的授权牌
+      currentCard: null,
+      rules: {
+        templateImage: [{ required: true, message: '请上传授权牌模板', trigger: ['change'] }],
+        authUserId: [{ required: true, message: '请选择供应商', trigger: ['change'] }],
+        qrPosition: [{ validator: validateQrPosition, trigger: ['blur'] }],
+        qrSize: [{ required: true, message: '请填写二维码大小', trigger: ['blur'] }],
+        logoSize: [
+          { required: true, message: '请输入授权牌logo建议尺寸宽高', trigger: ['blur'] },
+          { validator: validateLogoSize, trigger: ['blur'] }
+        ]
+      }
+    }
+  },
+  created() {
+    this.getList()
+    this.fetchSupplierList()
+  },
+  methods: {
+    // 获取授权牌模板列表
+    getList() {
+      this.list = []
+      this.listQuery.pageNum = 1
+      this.fetchAuthTempList(this.listQuery)
+    },
+
+    // 获取授权牌模板列表
+    async fetchAuthTempList() {
+      this.listLoading = true
+      try {
+        const res = await fetchAuthTempList(this.listQuery)
+        this.list = res.data.list
+        this.total = res.data.total
+        this.listLoading = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+
+    // 编辑授权牌模板
+    onTempEdit(row) {
+      this.formData.templateId = row.templateId
+      this.formData.authUserId = row.authUserId
+      this.formData.qrPosition = row.qrPosition
+      this.formData.qrSize = row.qrSize
+      this.formData.logoSize = row.logoSize
+      this.formData.templateImage = row.templateImage
+      if (row.templateImage) {
+        this.tempList = [{ name: '授权牌模板', url: row.templateImage }]
+      }
+      this.addCardVisible = true
+    },
+
+    // 获取供应商列表
+    async fetchSupplierList() {
+      try {
+        const res = await fetchSupplierList({
+          listType: 1,
+          brandId: '', // 品牌id
+          linkMan: '', // 联系人
+          mobile: '', // 手机号
+          pageNum: 1, // 页码
+          pageSize: 1000, // 分页大小
+          shopName: '', // 供应商名称
+          shopType: '', // 供应商类型
+          loginAccount: '' // 登录账号
+        })
+        this.supplierList = res.data.list
+      } catch (error) {
+        console.log(error)
+      }
+    },
+
+    // 选中供应商
+    onSupplierConfirm(type, e) {
+      type === 'add' ? (this.addCardInnerVisible = false) : (this.selectSupplierVisible = false)
+      this.selectSupplier = e
+      this.formData.authUserId = e.authUserId
+      if (type === 'edit') {
+        this.onChangeSupplierSubmit()
+      }
+    },
+
+    // 修改供应商操作
+    onChangeSupplier(row) {
+      this.currentCard = row
+      this.selectSupplierVisible = true
+    },
+
+    // 修改模板启用状态
+    onTempStatusChange(row) {
+      row.status = row.status === 0 ? 1 : 0
+      this.authTempSave(row)
+    },
+
+    // 修改供应商提交
+    onChangeSupplierSubmit() {
+      this.currentCard.authUserId = this.formData.authUserId
+      this.authTempSave(this.currentCard)
+    },
+
+    // 修改授权牌供应商弹窗关闭
+    onSelectSupplierClose() {
+      this.onAddCardClose()
+    },
+
+    // 添加授权牌弹窗关闭
+    onAddCardClose() {
+      this.selectSupplier = null
+      this.formData.templateId = ''
+      this.formData.authUserId = ''
+      this.formData.qrPosition = ''
+      this.formData.qrSize = ''
+      this.formData.logoSize = ''
+      this.formData.templateImage = ''
+      this.tempList = []
+      this.$refs.addCardForm?.clearValidate()
+    },
+
+    // 添加授权牌提交
+    async onConfirm() {
+      try {
+        this.isLoading = true
+        await this.$refs.addCardForm.validate()
+        await this.authTempSave(this.formData)
+      } catch (error) {
+        console.log(error)
+      } finally {
+        this.isLoading = false
+      }
+    },
+
+    // 授权牌信息保存
+    async authTempSave(data) {
+      const submitData = objectCover(
+        {
+          templateId: '',
+          templateImage: '',
+          authUserId: '',
+          status: 1,
+          qrPosition: '',
+          logoSize: '',
+          qrSize: ''
+        },
+        data
+      )
+      try {
+        await authTempSave(submitData)
+        this.$message.success('操作成功')
+        this.getList()
+        this.addCardVisible = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+
+    // 授权牌模板上传
+    uploadTempImageSuccess({ response, file, fileList }) {
+      this.tempList = fileList
+      this.formData.templateImage = response.data
+    },
+    handleLogoImageRemove({ file, fileList }) {
+      this.tempList = fileList
+      this.formData.templateImage = ''
+    },
+
+    // 表格序号
+    indexMethod(index) {
+      return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.el-image {
+  max-width: 120px;
+  max-height: 30px;
+  display: block;
+  margin: 0 auto;
+}
+
+.current-info {
+  font-size: 14px;
+  .supplier-name {
+    color: #333;
+    margin-right: 6px;
+  }
+  .supplier-change {
+    color: #409eff;
+    text-decoration: underline;
+    cursor: pointer;
+  }
+}
+</style>

+ 0 - 36
src/views/admin/settings/menus/children-list.vue

@@ -1,36 +0,0 @@
-<template>
-  <div class="app-container">
-    <el-page-header :content="title" @back="goBack" />
-    <table-list :menu-type="menuType" />
-  </div>
-</template>
-
-<script>
-import TableList from './components/table-list.vue'
-export default {
-  components: {
-    TableList
-  },
-  data() {
-    return {
-      menuType: 1,
-      title: ''
-    }
-  },
-  created() {
-    this.menuType = parseInt(this.$route.params.menuType)
-    this.title = `所属父级菜单:${this.$route.params.title}`
-  },
-  methods: {
-    goBack() {
-      this.$router.back()
-    }
-  }
-}
-</script>
-
-<style scoped>
-.el-page-header{
-  margin-bottom: 16px;
-}
-</style>

+ 385 - 0
src/views/admin/settings/menus/components/edit-page.vue

@@ -0,0 +1,385 @@
+<template>
+  <el-drawer :title="title" :visible.sync="visible" size="40%" :before-close="onBeforeClose">
+    <div class="menus-edit">
+      <div class="menus-edit-form">
+        <el-form ref="menuFrom" label-width="100px" :model="menuData" :rules="rules">
+          <el-form-item label="父级菜单:" prop="parentId">
+            <el-cascader
+              v-model="menuData.parentId"
+              style="width: 100%"
+              :options="menuOptions"
+              :props="menuProps"
+              placeholder="请选择父级菜单,不选默认为顶级菜单"
+              clearable
+            />
+          </el-form-item>
+          <el-form-item label="菜单名称:" prop="title">
+            <el-input v-model="menuData.title" placeholder="菜单名称" />
+          </el-form-item>
+          <el-form-item label="路由名称:" prop="name">
+            <el-input v-model="menuData.name" placeholder="路由名称" />
+          </el-form-item>
+          <el-form-item label="显示隐藏:">
+            <el-radio-group v-model="menuData.hidden">
+              <el-radio :label="0">显示</el-radio>
+              <el-radio :label="1">隐藏</el-radio>
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item label="前端图标:">
+            <el-popover v-model="showIcons" placement="bottom" width="400" trigger="click">
+              <icon-list @click="onChooseIcon" />
+              <div slot="reference">
+                <el-input v-model="menuData.icon" style="width: 80%" placeholder="选择图标" clearable>
+                  <template><el-button slot="append" icon="el-icon-edit" /></template>
+                </el-input>
+                <template>
+                  <i v-if="isElementIcon(menuData.icon)" :class="menuData.icon" class="preview-icon" />
+                  <i v-if="isOurIcon(menuData.icon)" :class="menuData.icon" class="preview-icon" />
+                  <svg-icon v-else-if="menuData.icon" :icon-class="menuData.icon" class="preview-icon" />
+                </template>
+              </div>
+            </el-popover>
+          </el-form-item>
+          <template v-if="!parentMenuData && menuType !== 1">
+            <el-form-item label="功能类型:" prop="baseFlag">
+              <el-radio-group v-model="menuData.baseFlag">
+                <el-radio :label="1">基础功能</el-radio>
+                <el-radio :label="0">会员特定</el-radio>
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item label="功能切换:" prop="moveFlag">
+              <el-radio-group v-model="menuData.moveFlag">
+                <el-radio :label="1">允许</el-radio>
+                <el-radio :label="0">禁止</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </template>
+          <el-form-item label="状态:">
+            <el-radio-group v-model="menuData.status">
+              <el-radio :label="0">启用</el-radio>
+              <el-radio :label="1">停用</el-radio>
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item label="排序:">
+            <el-input v-model="menuData.sort" />
+          </el-form-item>
+          <el-form-item label="按钮权限:">
+            <template>
+              <el-input v-show="false" v-model="menuData.permissionJson" />
+              <el-table border :data="permissions">
+                <el-table-column label="按钮名称" align="center">
+                  <template slot-scope="{ row }">
+                    <el-input v-model="row.title" size="mini" />
+                  </template>
+                </el-table-column>
+                <el-table-column label="权限标识" align="center">
+                  <template slot-scope="{ row }">
+                    <el-input v-model="row.name" size="mini" />
+                  </template>
+                </el-table-column>
+                <el-table-column label="操作" align="center">
+                  <template slot-scope="{ row }">
+                    <el-button type="danger" size="mini" @click="removeOne(row.uuid)">删除按钮</el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+              <div style="text-align: center; margin-top: 24px">
+                <el-button type="primary" size="mini" @click="insertOne">添加按钮</el-button>
+              </div>
+            </template>
+          </el-form-item>
+        </el-form>
+      </div>
+      <!-- 确认 取消 -->
+      <div class="control-box">
+        <el-button type="warning" @click="cancel">取消</el-button>
+        <el-button type="primary" @click="submit">保存</el-button>
+      </div>
+    </div>
+  </el-drawer>
+</template>
+
+<script>
+import { createMenu, getMenu, updateMenu, sysMenuTree } from '@/api/system'
+import IconList from '@/components/IconList'
+import { deepClone } from '@/utils'
+let uuid = 0
+const menuData = () => ({
+  id: '',
+  title: '',
+  name: '',
+  icon: '',
+  hidden: 0,
+  status: 0,
+  sort: 0,
+  childCount: 0,
+  permissionJson: '',
+  parentId: 0,
+  baseFlag: 1,
+  moveFlag: 1,
+  menuType: 1
+})
+
+export default {
+  name: 'EditPage',
+  components: {
+    IconList
+  },
+  props: {
+    show: {
+      type: Boolean,
+      default: false
+    },
+    title: {
+      type: String,
+      default: 'add'
+    },
+    // 编辑类型
+    editType: {
+      type: String,
+      default: 'add'
+    },
+    // 菜单类型
+    menuType: {
+      type: Number,
+      default: 1
+    },
+    // 菜单id
+    menuId: {
+      type: Number,
+      default: 0
+    }
+  },
+  data() {
+    return {
+      menuOptions: [],
+      visible: false,
+      showIcons: false,
+      // 上级菜单信息
+      parentMenuData: null,
+      // 表单参数
+      menuData: menuData(),
+      // 按钮权限列表
+      permissions: [],
+      // 验证规则
+      rules: {
+        title: [{ required: true, message: '菜单名称不能为空', trigger: 'blur' }],
+        name: [{ required: true, message: '路由名称不能为空', trigger: 'blur' }]
+      },
+      menuProps: {
+        value: 'id',
+        label: 'title',
+        children: 'subMenus',
+        emitPath: false,
+        checkStrictly: true
+      }
+    }
+  },
+  watch: {
+    show(nval) {
+      if (nval) {
+        this.visible = nval
+        this.init()
+      }
+    },
+    visible(nval) {
+      if (!nval) this.$emit('close')
+    }
+  },
+  methods: {
+    onChooseIcon(item) {
+      this.showIcons = false
+      this.menuData.icon = item
+    },
+    // 选择图标
+    handleChooseIcon() {
+      this.showIcons = true
+    },
+
+    // 初始化
+    init() {
+      this.menuData = menuData()
+      this.parentMenuData = null
+      this.permissions = []
+      console.log('menuId', this.menuId)
+
+      this.menuData.menuType = this.menuType
+      this.fetchMenuList()
+      // 编辑修改菜单
+      if (this.editType === 'edit') {
+        this.menuData.id = this.menuId
+        this.fetchMenuInfo()
+      } else if (this.editType === 'child') {
+        this.menuData.parentId = this.menuId.toString()
+      }
+    },
+
+    // 获取父菜单信息
+    fetchParentMenuInfo() {
+      getMenu(this.menuData.parentId).then((res) => {
+        this.parentMenuData = res.data
+        this.menuData.baseFlag = res.data.baseFlag
+      })
+    },
+
+    // 获取父级菜单列表
+    async fetchMenuList() {
+      try {
+        const res = await sysMenuTree({ menuType: this.menuType })
+        this.menuOptions = res.data
+      } catch (error) {
+        console.log(error)
+      }
+    },
+
+    // 获取菜单数据
+    fetchMenuInfo() {
+      getMenu(this.menuData.id).then((res) => {
+        this.setMenuData(res.data)
+      })
+    },
+
+    // 设置菜单数据(编辑时调用)
+    setMenuData(data) {
+      for (const key in this.menuData) {
+        if (Object.hasOwnProperty.call(data, key)) {
+          this.menuData[key] = data[key]
+        }
+      }
+      // 按钮权限列表
+      if (this.permissionJson) {
+        this.permissions = JSON.parse(this.permissionJson)
+      }
+      // 父级菜单信息
+      if (this.menuData.parentId > 0) {
+        this.menuData.parentId = this.menuData.parentId.toString()
+      }
+    },
+
+    // 判断图标类型
+    isElementIcon(value) {
+      return value && value.substr(0, 7) === 'el-icon'
+    },
+
+    // 判断自定义图标
+    isOurIcon(value) {
+      return value && value.startsWith('iconfont')
+    },
+
+    // 提交
+    submit() {
+      console.log(this.menuData)
+      this.menuData.permissionJson = JSON.stringify(this.permissions)
+      this.$refs.menuFrom.validate((valide) => {
+        if (!valide) return
+        if (this.editType === 'add' || this.editType === 'child') {
+          this.createMenu()
+        } else {
+          this.updateMenu()
+        }
+      })
+    },
+
+    // 修改菜单
+    async updateMenu() {
+      try {
+        const menuData = deepClone(this.menuData)
+        menuData.parentId = parseInt(menuData.parentId)
+        await updateMenu(this.menuData.id, this.menuData)
+        this.$message.success('修改菜单成功')
+        this.$emit('success')
+        this.$refs.menuFrom.clearValidate()
+        this.visible = false
+      } catch (error) {
+        this.$emit('error')
+      }
+    },
+
+    // 添加菜单
+    async createMenu() {
+      try {
+        const menuData = deepClone(this.menuData)
+        menuData.parentId = parseInt(menuData.parentId)
+        await createMenu(this.menuData)
+        this.$message.success('添加菜单成功')
+        this.$emit('success')
+        this.$refs.menuFrom.clearValidate()
+        this.visible = false
+      } catch (error) {
+        this.$emit('error')
+      }
+    },
+
+    cancel() {
+      this.visible = false
+    },
+
+    // 添加按钮权限
+    insertOne() {
+      this.permissions.push({
+        uuid: ++uuid,
+        name: '',
+        title: ''
+      })
+    },
+
+    // 移除一条按钮权限
+    removeOne(uuid) {
+      const index = this.permissions.findIndex((item) => item.uuid === uuid)
+      this.permissions.splice(index, 1)
+    },
+
+    onBeforeClose(done) {
+      this.$confirm('您有数据未保存, 是否继续?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      })
+        .then(() => {
+          this.$refs.menuFrom.clearValidate()
+          done()
+        })
+        .catch(() => {
+          this.$message({
+            type: 'info',
+            message: '已取消关闭'
+          })
+        })
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.menus-edit {
+  position: relative;
+  height: calc(100vh - 45px);
+
+  .menus-edit-form {
+    overflow-y: auto;
+    height: 100%;
+    box-sizing: border-box;
+    padding: 24px 12px 60px;
+  }
+
+  .preview-icon {
+    font-size: 24px;
+    margin-left: 8px;
+  }
+}
+.control-box {
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  text-align: center;
+  background: #fff;
+  border-top: 1px solid #ebebeb;
+  padding: 12px 0;
+  z-index: 9;
+  .el-button {
+    width: 120px;
+    margin: 0 8px;
+  }
+}
+</style>

+ 232 - 163
src/views/admin/settings/menus/components/table-list.vue

@@ -1,96 +1,126 @@
 <template>
   <div class="table-list">
-    <div class="filter-container">
-      <div class="filter-control">
-        <span>菜单状态:</span>
-        <el-select
-          v-model="listQuery.status"
-          placeholder="启用状态"
-          clearable
-          style="width: 200px"
-          class="filter-item"
-          @change="getList"
-        >
-          <el-option label="全部" value="" />
-          <el-option label="已启用" :value="0" />
-          <el-option label="未启用" :value="1" />
-        </el-select>
-      </div>
-      <div class="filter-control">
-        <el-button type="primary" @click="handleAddMenu()">添加菜单</el-button>
+    <div class="app-container">
+      <div class="filter-container">
+        <div class="filter-control">
+          <span>菜单状态:</span>
+          <el-select
+            v-model="listQuery.status"
+            placeholder="启用状态"
+            clearable
+            style="width: 200px"
+            class="filter-item"
+            @change="getList"
+          >
+            <el-option label="全部" value="" />
+            <el-option label="已启用" :value="0" />
+            <el-option label="未启用" :value="1" />
+          </el-select>
+        </div>
+        <div class="filter-control">
+          <el-button type="primary" @click="onEditMenu(null, 'add')">添加菜单</el-button>
+        </div>
       </div>
+      <!-- 搜索区域END -->
+      <el-table
+        v-loading="listLoading"
+        class="table-cell"
+        row-key="id"
+        header-row-class-name="tableHeader"
+        border
+        fit
+        lazy
+        :data="list"
+        :load="load"
+        :tree-props="{ hasChildren: 'hasChildren' }"
+      >
+        <el-table-column :index="indexMethod" prop="title" label="序号" type="index" width="60" align="center" />
+        <el-table-column label="菜单名称" prop="title">
+          <template slot-scope="{ row }">
+            <span v-if="!row.hasChildren" style="margin-right: 23px" />
+            <span>{{ row.title }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="name" label="路由名称" align="center" />
+        <el-table-column label="级别" width="120px" align="center">
+          <template slot-scope="{ row }">
+            {{ row.level | levelName }}
+          </template>
+        </el-table-column>
+        <!-- <el-table-column prop="childCount" label="子菜单数量" align="center" width="100px" /> -->
+        <el-table-column label="图标" align="center" width="80">
+          <template slot-scope="{ row }">
+            <template v-if="row.icon">
+              <i v-if="isElementIcon(row.icon)" :class="row.icon" />
+              <i v-else-if="isOurIcon(row.icon)" :class="row.icon" />
+              <svg-icon v-else :icon-class="row.icon" />
+            </template>
+            <span v-else>无</span>
+          </template>
+        </el-table-column>
+        <el-table-column v-if="listQuery.menuType === 2" prop="name" label="功能类别" align="center" width="80px">
+          <template slot-scope="{ row }">
+            <span v-if="row.baseFlag === 1">基础</span>
+            <span v-else>订制</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="启用状态" align="center" width="100">
+          <template slot-scope="{ row }">
+            <el-switch v-model="row.status" :active-value="0" :inactive-value="1" @change="onUpdateMenuStatus(row)" />
+          </template>
+        </el-table-column>
+        <el-table-column prop="sort" label="排序" align="center" width="80">
+          <template slot-scope="{ row }">
+            <el-input v-model.number="row.sort" @blur="onUpdateMenuSort(row)" />
+          </template>
+        </el-table-column>
+        <el-table-column label="创建时间" align="center" width="180px">
+          <template slot-scope="{ row }">
+            <span>{{ row.createTime | formatTime }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" align="center" width="260">
+          <template slot-scope="{ row }">
+            <el-button type="primary" size="mini" @click="onEditMenu(row, 'edit')">编辑</el-button>
+            <el-button type="primary" size="mini" @click="onEditMenu(row, 'child')">添加子菜单</el-button>
+            <el-button type="danger" size="mini" @click="onDeleteMenu(row)">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <!-- 页码 -->
+      <pagination
+        :total="total"
+        :page.sync="listQuery.pageNum"
+        :limit.sync="listQuery.pageSize"
+        @pagination="getList"
+      />
+      <edit-page
+        :title="editTitle"
+        :show="editDrawer"
+        :menu-type="menuType"
+        :edit-type="editType"
+        :menu-id="currentMenuId"
+        @close="editDrawer = false"
+        @success="onEditSuccess"
+      />
     </div>
-    <!-- 搜索区域END -->
-    <el-table
-      v-loading="listLoading"
-      :data="list"
-      style="width: 100%"
-      border
-      fit
-      header-row-class-name="tableHeader"
-      class="table-cell"
-    >
-      <el-table-column :index="indexMethod" label="序号" type="index" width="80" align="center" />
-      <el-table-column prop="title" label="菜单名称" align="center" />
-      <el-table-column prop="name" label="路由名称" align="center" />
-      <el-table-column label="展示图标" align="center" width="100">
-        <template slot-scope="{ row }">
-          <i v-if="row.icon" :class="row.icon" />
-          <span v-else>无</span>
-        </template>
-      </el-table-column>
-      <el-table-column v-if="listQuery.menuType === 2" prop="name" label="会员功能" align="center">
-        <template slot-scope="{ row }">
-          <span v-if="row.baseFlag === 1">基础功能</span>
-          <span v-else>订制功能</span>
-        </template>
-      </el-table-column>
-      <el-table-column label="启用状态" align="center" width="100">
-        <template slot-scope="{ row }">
-          <el-switch v-model="row.status" :active-value="0" :inactive-value="1" @change="updateMenuStatus(row)" />
-        </template>
-      </el-table-column>
-      <el-table-column prop="sort" label="排序" align="center" width="100">
-        <template slot-scope="{ row }">
-          <el-input v-model="row.sort" @change="updateMenuSort(row)" />
-        </template>
-      </el-table-column>
-      <el-table-column label="子菜单管理" align="center" width="240">
-        <template slot-scope="{ row }">
-          <el-button size="mini" @click="handleSearchChildren(row)">查看子菜单</el-button>
-          <el-button size="mini" @click="handleAddMenu(row)">添加子菜单</el-button>
-        </template>
-      </el-table-column>
-      <el-table-column label="操作" align="center" width="200">
-        <template slot-scope="{ row }">
-
-          <el-button
-            type="primary"
-            size="mini"
-            @click="handleEditMenu(row)"
-          >编辑</el-button>
-          <el-button type="danger" size="mini" @click="deleteMenu(row)">删除</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <!-- 页码 -->
-    <pagination
-      v-show="total > 0"
-      :total="total"
-      :page.sync="listQuery.pageNum"
-      :limit.sync="listQuery.pageSize"
-      @pagination="getList"
-    />
   </div>
 </template>
 
 <script>
-import { fetchMenuList, deleteMenu, updateMenuSelective } from '@/api/system'
-import Pagination from '@/components/Pagination' // secondary package based on el-pagination
+import { fetchMenuList, updateMenuSelective, deleteMenu } from '@/api/system'
+import Pagination from '@/components/Pagination'
+import EditPage from './edit-page.vue'
 export default {
   name: 'TableList',
   components: {
-    Pagination
+    Pagination,
+    EditPage
+  },
+  filters: {
+    levelName(level) {
+      return '一二三四五六七八九十'.split('')[level - 1] + '级菜单'
+    }
   },
   props: {
     menuType: {
@@ -101,6 +131,8 @@ export default {
   data() {
     return {
       listLoading: false,
+      editDrawer: false,
+      editTitle: '',
       // 查询参数
       listQuery: {
         parentId: '',
@@ -111,111 +143,149 @@ export default {
       },
       total: 0,
       // 菜单列表
-      list: []
+      list: [],
+      currentMenuId: 0,
+      currentParentId: 0,
+      editType: 'add'
     }
   },
   created() {
-    this.initQuery()
     this.getList()
   },
   methods: {
-    // 初始化参数
-    initQuery() {
-      const { id = '', title = '' } = this.$route.params
-      this.listQuery.menuType = this.menuType
-      this.parentTitle = title
-      this.listQuery.parentId = id
+    // 编辑菜单
+    onEditMenu(row, type) {
+      this.editType = type
+      const titles = {
+        edit: '修改菜单信息',
+        add: '添加菜单',
+        child: '添加子菜单'
+      }
+      this.editTitle = titles[type]
+      if (type === 'edit') {
+        this.currentMenuId = row.id
+        this.currentParentId = row.parentId
+      } else if (type === 'child') {
+        this.currentMenuId = row.id
+      } else {
+        this.currentMenuId = 0
+      }
+      this.editDrawer = true
     },
-    // 添加菜单
-    handleAddMenu(row) {
-      if (row) {
-        this.$router.push({
-          path: '/settings/menus/children/add',
-          query: {
-            type: 'add',
-            parentId: row.id,
-            menuType: this.menuType
-          }
-        })
-      } else if (this.listQuery.parentId) {
-        this.$router.push({
-          path: '/settings/menus/children/add',
-          query: {
-            type: 'add',
-            parentId: this.listQuery.parentId,
-            menuType: this.menuType
-          }
+
+    // 加载子菜单
+    async load(tree, treeNode, resolve) {
+      try {
+        const res = await fetchMenuList({
+          parentId: tree.id,
+          menuType: this.menuType,
+          status: '',
+          pageSize: 1000,
+          pageNum: 1
         })
-      } else {
-        this.$router.push({
-          path: '/settings/menus/add',
-          query: {
-            type: 'add',
-            menuType: this.menuType
-          }
+        const list = res.data.list.map((item) => {
+          item.hasChildren = item.childCount > 0
+          item.level = tree.level + 1
+          item.rowId = tree.rowId + '-' + item.id
+          return item
         })
+        this.$set(tree, 'chidlren', list) // 菜单列表
+        resolve(list)
+      } catch (error) {
+        console.log(error)
       }
     },
-    // 查看子菜单
-    handleSearchChildren(row) {
-      this.listQuery.parentId = row.id
-      this.$router.replace(`/settings/menus/children/${this.menuType}/${row.id}/${row.title}`)
-    },
-    // 修改菜单
-    handleEditMenu(row) {
-      // $_navigationTo(`/settings/menus/edit?id=${row.id}&type=edit`)
-      this.$router.push({
-        path: '/settings/menus/edit',
-        query: {
-          id: row.id,
-          type: 'edit',
-          menuType: this.menuType
-        }
-      })
-    },
+
     // 获取列表
-    getList() {
+    async getList() {
+      this.listQuery.menuType = this.menuType
       this.listQuery.pageNum = 1
-      this.list = []
-      this.fetchMenuList()
-    },
-    // 获取菜单列表
-    fetchMenuList() {
-      fetchMenuList(this.listQuery).then(res => {
-        this.list = [...this.list, ...res.data.list]
+      try {
+        const res = await fetchMenuList(this.listQuery)
+        this.list = res.data.list.map((item) => {
+          item.hasChildren = item.childCount > 0
+          item.level = 1
+          item.rowId = item.id + ''
+          return item
+        })
         this.total = res.data.total
+      } catch (error) {
+        console.log(error)
+      }
+    },
+
+    // 编辑成功
+    onEditSuccess() {
+      this.$store.dispatch('tagsView/delCachedView', this.$route).then(() => {
+        const { fullPath } = this.$route
+        this.$nextTick(() => {
+          this.$router.replace({
+            path: '/redirect' + fullPath
+          })
+        })
       })
     },
+
     // 更新状态
-    updateMenuStatus(row) {
-      updateMenuSelective(row.id, { status: row.status }).then(() => {
+    async onUpdateMenuStatus(row) {
+      try {
+        await updateMenuSelective(row.id, { status: row.status })
         this.$message.success('操作成功')
-      })
+      } catch (error) {
+        console.log(error)
+      } finally {
+        this.onEditSuccess()
+      }
     },
+
     // 更新排序
-    updateMenuSort(row) {
-      updateMenuSelective(row.id, { sort: row.sort }).then(() => {
+    async onUpdateMenuSort(row) {
+      try {
+        await updateMenuSelective(row.id, { sort: row.sort })
         this.$message.success('操作成功')
-        this.getList()
-      })
+      } catch (error) {
+        console.log(error)
+      } finally {
+        this.onEditSuccess()
+      }
     },
+
     // 删除菜单
-    deleteMenu(row) {
-      this.$confirm('此操作将永久删除该菜单及其子菜单, 是否继续?', '提示', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        type: 'warning'
-      })
-        .then(() => {
-          deleteMenu(row.id).then(res => {
-            this.$message.success('删除成功')
-            this.getList()
-          })
-        })
-        .catch(() => {
-          this.$message.info('已取消删除')
+    async deleteMenu(row) {
+      try {
+        await deleteMenu(row.id)
+        this.$message.success('删除成功')
+      } catch (error) {
+        console.log(error)
+      } finally {
+        this.onEditSuccess()
+      }
+    },
+
+    // 删除菜单操作
+    async onDeleteMenu(row) {
+      try {
+        await this.$confirm('此操作将永久删除该菜单及其子菜单, 是否继续?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
         })
+        this.deleteMenu(row)
+      } catch (error) {
+        this.$message.info('已取消删除')
+      }
     },
+
+    // 判断图标类型
+    isElementIcon(value) {
+      return value && value.substr(0, 7) === 'el-icon'
+    },
+
+    // 判断自定义图标
+    isOurIcon(value) {
+      return value && value.startsWith('iconfont')
+    },
+
     // 表格索引
     indexMethod(index) {
       return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1
@@ -224,4 +294,3 @@ export default {
 }
 </script>
 
-<style scoped></style>

+ 0 - 277
src/views/admin/settings/menus/edit.vue

@@ -1,277 +0,0 @@
-<template>
-  <div class="app-container menus-edit">
-    <el-form ref="menuFrom" label-width="100px" :model="menuData" :rules="rules">
-      <el-form-item v-if="parentMenuData" label="上级菜单:">
-        <el-input v-model="parentMenuData.title" placeholder="上级菜单" readonly />
-      </el-form-item>
-      <el-form-item label="菜单名称:" prop="title">
-        <el-input v-model="menuData.title" placeholder="菜单名称" />
-      </el-form-item>
-      <el-form-item label="路由名称:" prop="name">
-        <el-input v-model="menuData.name" placeholder="路由名称" />
-      </el-form-item>
-      <el-form-item label="显示隐藏:">
-        <el-radio-group v-model="menuData.hidden">
-          <el-radio :label="0">显示</el-radio>
-          <el-radio :label="1">隐藏</el-radio>
-        </el-radio-group>
-      </el-form-item>
-      <el-form-item label="前端图标:">
-        <el-input v-model="menuData.icon" style="width: 80%" placeholder="选择图标" clearable>
-          <template><el-button slot="append" icon="el-icon-edit" @click="handleChooseIcon" /></template>
-        </el-input>
-        <template>
-          <i v-if="isElementIcon(menuData.icon)" :class="menuData.icon" class="preview-icon" />
-          <i v-if="isOurIcon(menuData.icon)" :class="menuData.icon" class="preview-icon" />
-          <svg-icon v-else-if="menuData.icon" :icon-class="menuData.icon" class="preview-icon" />
-        </template>
-      </el-form-item>
-      <template v-if="!parentMenuData && menuType!== 1">
-        <el-form-item label="功能类型:" prop="baseFlag">
-          <el-radio-group v-model="menuData.baseFlag">
-            <el-radio :label="1">基础功能</el-radio>
-            <el-radio :label="0">会员特定</el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="功能切换:" prop="moveFlag">
-          <el-radio-group v-model="menuData.moveFlag">
-            <el-radio :label="1">允许</el-radio>
-            <el-radio :label="0">禁止</el-radio>
-          </el-radio-group>
-        </el-form-item>
-      </template>
-      <el-form-item label="状态:">
-        <el-radio-group v-model="menuData.status">
-          <el-radio :label="0">启用</el-radio>
-          <el-radio :label="1">停用</el-radio>
-        </el-radio-group>
-      </el-form-item>
-      <el-form-item label="排序:">
-        <el-input v-model="menuData.sort" />
-      </el-form-item>
-      <el-form-item label="按钮权限:">
-        <template>
-          <el-input v-show="false" v-model="menuData.permissionJson" />
-          <el-table border :data="permissions">
-            <el-table-column label="按钮名称" align="center">
-              <template slot-scope="{row}">
-                <el-input v-model="row.title" size="mini" />
-              </template>
-            </el-table-column>
-            <el-table-column label="权限标识" align="center">
-              <template slot-scope="{row}">
-                <el-input v-model="row.name" size="mini" />
-              </template>
-            </el-table-column>
-            <el-table-column label="操作" align="center">
-              <template slot-scope="{ row }">
-                <el-button type="danger" size="mini" @click="removeOne(row.uuid)">删除按钮</el-button>
-              </template>
-            </el-table-column>
-          </el-table>
-          <div style="text-align:center;margin-top: 24px">
-            <el-button type="primary" size="mini" @click="insertOne">添加按钮</el-button>
-          </div>
-          <el-divider />
-        </template>
-      </el-form-item>
-      <el-form-item>
-        <!-- 确认 取消 -->
-        <div class="control-box">
-          <el-button type="warning" @click="$_back">返回</el-button>
-          <el-button type="primary" @click="submit">保存</el-button>
-        </div>
-      </el-form-item>
-    </el-form>
-
-    <!-- 选择图标icons -->
-    <el-dialog
-      title="提示"
-      :visible.sync="showIcons"
-      width="80%"
-    >
-      <icon-list @click="onChooseIcon" />
-    </el-dialog>
-  </div>
-</template>
-
-<script>
-import { createMenu, getMenu, updateMenu } from '@/api/system'
-import IconList from '@/components/IconList'
-let uuid = 0
-export default {
-  components: {
-    IconList
-  },
-  data() {
-    return {
-      showIcons: false,
-      // 编辑类型
-      editType: 'add',
-      menuType: '',
-      // 上级菜单信息
-      parentMenuData: null,
-      // 表单参数
-      menuData: {
-        id: '',
-        title: '',
-        name: '',
-        icon: '',
-        hidden: 0,
-        status: 0,
-        sort: 0,
-        childCount: 0,
-        permissionJson: '',
-        parentId: 0,
-        baseFlag: 1,
-        moveFlag: 1,
-        menuType: 1
-      },
-      // 按钮权限列表
-      permissions: [],
-      // 验证规则
-      rules: {
-        title: [{ required: true, message: '菜单名称不能为空', trigger: 'blur' }],
-        name: [{ required: true, message: '路由名称不能为空', trigger: 'blur' }]
-      }
-    }
-  },
-  created() {
-    this.editType = this.$route.query.type
-    this.init()
-  },
-  methods: {
-    onChooseIcon(item) {
-      this.showIcons = false
-      this.menuData.icon = item
-    },
-    // 选择图标
-    handleChooseIcon() {
-      this.showIcons = true
-    },
-    // 初始化
-    init() {
-      this.menuType = parseInt(this.$route.query.menuType)
-      // 编辑修改菜单
-      if (this.editType === 'edit') {
-        this.menuData.id = parseInt(this.$route.query.id)
-        this.fetchMenuInfo()
-      }
-      // 添加菜单
-      if (this.editType === 'add') {
-        this.menuData.parentId = parseInt(this.$route.query.parentId)
-        this.menuData.menuType = this.menuType
-        console.log(this.menuType)
-        if (this.menuData.parentId > 0) {
-          this.fetchParentMenuInfo()
-        }
-      }
-    },
-    // 获取父菜单信息
-    fetchParentMenuInfo() {
-      getMenu(this.menuData.parentId).then(res => {
-        this.parentMenuData = res.data
-        this.menuData.baseFlag = res.data.baseFlag
-        console.log(res.data)
-      })
-    },
-    // 获取菜单数据
-    fetchMenuInfo() {
-      getMenu(this.menuData.id).then(res => {
-        console.log(res)
-        this.setMenuData(res.data)
-      })
-    },
-    // 设置菜单数据
-    setMenuData(data) {
-      for (const key in this.menuData) {
-        if (Object.hasOwnProperty.call(data, key)) {
-          this.menuData[key] = data[key]
-        }
-      }
-      // 按钮权限列表
-      if (this.permissionJson) {
-        this.permissions = JSON.parse(this.permissionJson)
-      }
-      // 父级菜单信息
-      if (this.menuData.parentId > 0) {
-        this.fetchParentMenuInfo()
-      }
-    },
-    // 判断图标类型
-    isElementIcon(value) {
-      return value && value.substr(0, 7) === 'el-icon'
-    },
-    // 判断自定义图标
-    isOurIcon(value) {
-      return value && value.startsWith('iconfont')
-    },
-    // 提交
-    submit() {
-      console.log(this.menuData)
-      this.menuData.permissionJson = JSON.stringify(this.permissions)
-      this.$refs.menuFrom.validate(valide => {
-        if (!valide) return
-        if (this.editType === 'add') {
-          this.createMenu()
-        } else {
-          this.updateMenu()
-        }
-      })
-    },
-    // 修改菜单
-    updateMenu() {
-      updateMenu(this.menuData.id, this.menuData).then(res => {
-        this.$message.success('修改菜单成功')
-        this.$store.dispatch('tagsView/delView', this.$route)
-        this.$router.back()
-      })
-    },
-    // 添加菜单
-    createMenu() {
-      console.log(this.menuData)
-      // return
-      createMenu(this.menuData).then(res => {
-        console.log(res)
-        this.$message.success('添加菜单成功')
-        this.$store.dispatch('tagsView/delView', this.$route)
-        this.$router.back()
-      })
-    },
-    // 添加按钮权限
-    insertOne() {
-      this.permissions.push({
-        uuid: ++uuid,
-        name: '',
-        title: ''
-      })
-    },
-    // 移除一条按钮权限
-    removeOne(uuid) {
-      const index = this.permissions.findIndex(item => item.uuid === uuid)
-      this.permissions.splice(index, 1)
-    }
-  }
-}
-</script>
-
-<style scoped lang="scss">
-.menus-edit {
-  width: 600px;
-  margin: 0 auto;
-  margin-top: 40px;
-
-  .preview-icon{
-    font-size: 24px;
-    margin-left: 8px;
-  }
-}
-.control-box {
-  margin: 20px 0;
-  text-align: center;
-  .el-button {
-    width: 120px;
-    margin: 0 8px;
-  }
-}
-</style>

+ 0 - 1
src/views/admin/settings/menus/index.vue

@@ -4,7 +4,6 @@
       <el-tab-pane v-for="item in menusCategory" :key="item.menuType" :label="item.title" :name="item.name" :lazy="true">
         <table-list :key="item.menuType" :menu-type="item.menuType" />
       </el-tab-pane>
-      <!-- <el-tab-pane label="供应商" name="second">配置管理</el-tab-pane> -->
     </el-tabs>
   </div>
 </template>

+ 1 - 14
src/views/admin/supplier/club/device/index.vue

@@ -74,19 +74,7 @@
 
       <el-table-column label="审核状态" width="120px" align="center">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.auditStatus === 2" size="small" type="warning">待审核</el-tag>
-          <el-tag v-if="row.auditStatus === 1" size="small" type="success">审核通过</el-tag>
-          <!-- 未通过原因展示 -->
-          <template v-if="row.auditStatus === 0">
-            <!-- <span class="status danger">审核未通过&nbsp;</span> -->
-            <el-popover placement="top-start" title="审核说明" width="400" trigger="hover" :content="row.invalidReason">
-              <el-tag slot="reference" size="small" type="danger" class="reason">
-                <span>审核未通过</span>
-                <span class="el-icon-question status danger " />
-              </el-tag>
-            </el-popover>
-            <!-- 未通过原因展示END -->
-          </template>
+          <audit-status :status="row.auditStatus" :reason="row.invalidReason" />
         </template>
       </el-table-column>
 
@@ -141,7 +129,6 @@
 
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 1 - 14
src/views/admin/supplier/club/index.vue

@@ -67,19 +67,7 @@
 
       <el-table-column label="审核状态" width="120px" align="center">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.auditStatus === 2" size="small" type="warning">待审核</el-tag>
-          <el-tag v-if="row.auditStatus === 1" size="small" type="success">审核通过</el-tag>
-          <!-- 未通过原因展示 -->
-          <template v-if="row.auditStatus === 0">
-            <!-- <span class="status danger">审核未通过&nbsp;</span> -->
-            <el-popover placement="top-start" title="审核说明" width="400" trigger="hover" :content="row.invalidReason">
-              <el-tag slot="reference" size="small" type="danger" class="reason">
-                <span>审核未通过</span>
-                <span class="el-icon-question status danger " />
-              </el-tag>
-            </el-popover>
-            <!-- 未通过原因展示END -->
-          </template>
+          <audit-status :status="row.auditStatus" :reason="row.invalidReason" />
         </template>
       </el-table-column>
 
@@ -130,7 +118,6 @@
 
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 40 - 24
src/views/admin/supplier/edit.vue

@@ -25,26 +25,33 @@
         />
       </el-form-item>
 
-      <el-form-item v-if="submitForm.shopType === 1" clearable label="供应商名称:" prop="brandId">
-        <el-select
-          v-if="editType === 'add'"
-          v-model="submitForm.brandId"
-          placeholder="请选择品牌"
-          style="width: 100%"
-          filterable
-          @change="handleBrandChange"
-        >
-          <el-option v-for="item in brandList" :key="item.id" :label="item.name" :value="item.id" />
-        </el-select>
-        <el-input
-          v-else
-          v-model="submitForm.shopName"
-          placeholder="请输入供应商名称"
-          maxlength="50"
-          show-word-limit
-          :disabled="editType === 'edit'"
-        />
-      </el-form-item>
+      <template v-if="submitForm.shopType === 1">
+        <el-form-item clearable label="供应商名称:" prop="brandId">
+          <el-select
+            v-if="editType === 'add'"
+            v-model="submitForm.brandId"
+            placeholder="请选择品牌"
+            style="width: 100%"
+            filterable
+            @change="handleBrandChange"
+          >
+            <el-option v-for="item in brandList" :key="item.id" :label="item.name" :value="item.id" />
+          </el-select>
+          <el-input
+            v-else
+            v-model="submitForm.shopName"
+            placeholder="请输入供应商名称"
+            maxlength="50"
+            show-word-limit
+            :disabled="editType === 'edit'"
+          />
+        </el-form-item>
+
+        <!-- 制造商 -->
+        <el-form-item label="制造商:">
+          <el-input v-model="submitForm.manufacturer" placeholder="请输入制造商名称" maxlength="50" show-word-limit />
+        </el-form-item>
+      </template>
       <!-- 供应商名称END -->
 
       <el-form-item label="手机号:" prop="mobile">
@@ -186,6 +193,10 @@
           </el-select>
         </el-form-item>
 
+        <el-form-item label="制造商:">
+          <el-input v-model="subForm.manufacturer" placeholder="请输入制造商名称" maxlength="50" show-word-limit />
+        </el-form-item>
+
         <el-form-item label="品牌logo:" class="no-input" prop="brandAuthLogo">
           <upload-image
             tip="建议尺寸:200px * 200px"
@@ -312,7 +323,8 @@ export default {
         appId: '',
         appSecret: '',
         qrCodeImage: '', // 微信公众号二维码
-        logo: '' // 代理商logo
+        logo: '', // 代理商logo
+        manufacturer: '' // 制造商
       },
       // 表单2
       subForm: {
@@ -324,7 +336,8 @@ export default {
         statementContent: '', // 声明内容
         statementFileId: null, // 声明文件id
         statementImage: '', // 声明图片
-        statementLink: '' // 声明链接
+        statementLink: '', // 声明链接
+        manufacturer: '' // 制造商
       },
       supplierBrands: [],
       brandList: [],
@@ -430,6 +443,7 @@ export default {
         this.submitForm.countryId = shopInfo.countryId
         this.submitForm.brandAuthLogo = shopInfo.brandAuthLogo
         this.submitForm.securityLink = shopInfo.securityLink
+        this.submitForm.manufacturer = shopInfo.manufacturer
         this.submitForm.brandName = shopInfo.brandName
 
         if (shopInfo.brandAuthLogo) {
@@ -504,7 +518,8 @@ export default {
         wxAccountType: 2,
         appId: '',
         appSecret: '',
-        qrCodeImage: '' // 微信公众号二维码
+        qrCodeImage: '', // 微信公众号二维码
+        manufacturer: '' // 制造商
       }
       for (const key in params) {
         if (Object.hasOwnProperty.call(this.submitForm, key)) {
@@ -546,6 +561,7 @@ export default {
           countryId: this.submitForm.countryId,
           brandAuthLogo: this.submitForm.brandAuthLogo,
           securityLink: this.submitForm.securityLink,
+          manufacturer: this.submitForm.manufacturer, // 制造商
           statementType: 1,
           statementContent: '',
           statementFileId: null,
@@ -553,7 +569,6 @@ export default {
           statementLink: ''
         }
       ]
-
       return params
     },
     // 大理上添加
@@ -674,6 +689,7 @@ export default {
     // 添加品牌对话框关闭
     handleDialogAddBrandClosed() {
       this.subForm.securityLink = ''
+      this.subForm.manufacturer = ''
       this.subForm.statementType = 1
       this.statementFileName = ''
       this.statementImageList = []

+ 2 - 19
src/views/admin/supplier/index.vue

@@ -5,7 +5,6 @@
         <span>供应商名称:</span>
         <el-input v-model="listQuery.shopName" placeholder="供应商名称" @keyup.enter.native="handleFilter" />
       </div>
-
       <div class="filter-control">
         <span>供应商类型:</span>
         <el-select
@@ -25,21 +24,6 @@
         <span>登录账号:</span>
         <el-input v-model="listQuery.loginAccount" placeholder="登录账号" @keyup.enter.native="handleFilter" />
       </div>
-      <!-- <div class="filter-control">
-        <span>所属品牌:</span>
-        <el-select
-          v-model="listQuery.brandId"
-          placeholder="所属品牌"
-          clearable
-          class="filter-item"
-          style="width: 200px"
-          filterable
-          @change="getList()"
-        >
-          <el-option label="所有品牌" value="" />
-          <el-option v-for="item in brandList" :key="item.id" :label="item.name" :value="item.id" />
-        </el-select>
-      </div> -->
       <div class="filter-control">
         <span>手机号:</span>
         <el-input
@@ -62,8 +46,8 @@
       </div>
 
       <div class="filter-control">
-        <el-button type="primary" @click="getList(listQuery)">查询</el-button>
-        <el-button type="primary" @click="$_navigationTo('supplier-add')">添加供应商</el-button>
+        <el-button size="mini" type="primary" @click="getList(listQuery)">查询</el-button>
+        <el-button size="mini" type="primary" @click="$_navigationTo('supplier-add')">添加供应商</el-button>
       </div>
     </div>
     <!-- 表格区域 -->
@@ -124,7 +108,6 @@
 
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 0 - 4
src/views/common/helper/document/index.vue

@@ -21,7 +21,6 @@
         <el-button type="primary" @click="getList">查询</el-button>
         <el-button
           v-if="userIdentity === 1"
-          icon="el-icon-edit"
           type="primary"
           @click="dialogVisible = true"
         >添加</el-button>
@@ -57,7 +56,6 @@
     </el-table>
     <!-- 表格区域END -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"
@@ -110,7 +108,6 @@ import Pagination from '@/components/Pagination' // secondary package based on e
 import openWindow from '@/utils/open-window'
 import { mapGetters } from 'vuex'
 import { fetchCourseList, saveCourse, removeCourse } from '@/api/helper'
-// import { getToutesTree, getModuleType } from '@/utils/formatRoutesToModule'
 import { debounce } from '@/utils/tools'
 import { sysMenuTree } from '@/api/system'
 export default {
@@ -171,7 +168,6 @@ export default {
   },
   created() {
     this.dialogFormData = this.resetDialogFormData()
-    // this.modules = getToutesTree(this.routes)
     this.getMenuTree()
   },
   methods: {

+ 0 - 4
src/views/common/helper/video/index.vue

@@ -21,7 +21,6 @@
         <el-button type="primary" @click="getList">查询</el-button>
         <el-button
           v-if="userIdentity === 1"
-          icon="el-icon-edit"
           type="primary"
           @click="dialogVisible = true"
         >添加</el-button>
@@ -57,7 +56,6 @@
     </el-table>
     <!-- 表格区域END -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"
@@ -105,7 +103,6 @@ import Pagination from '@/components/Pagination' // secondary package based on e
 import openWindow from '@/utils/open-window'
 import { mapGetters } from 'vuex'
 import { fetchCourseList, saveCourse, removeCourse } from '@/api/helper'
-// import { getToutesTree, getModuleType } from '@/utils/formatRoutesToModule'
 import { debounce } from '@/utils/tools'
 import { sysMenuTree } from '@/api/system'
 export default {
@@ -156,7 +153,6 @@ export default {
   },
   created() {
     this.dialogFormData = this.resetDialogFormData()
-    // this.modules = getToutesTree(this.routes)
     this.getMenuTree()
     console.log(this.authUserId)
   },

+ 2 - 20
src/views/normal/audit/club/components/club-list.vue

@@ -35,19 +35,7 @@
       <el-table-column label="手机号" width="120px" align="center" prop="mobile" />
       <el-table-column label="审核状态" width="120px" align="center">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.shopAuditStatus === 2" size="small" type="warning">待审核</el-tag>
-          <el-tag v-if="row.shopAuditStatus === 1" size="small" type="success">审核通过</el-tag>
-          <!-- 未通过原因展示 -->
-          <template v-if="row.shopAuditStatus === 0">
-            <!-- <span class="status danger">审核未通过&nbsp;</span> -->
-            <el-popover placement="top-start" title="审核说明" width="400" trigger="hover" :content="row.invalidReason">
-              <el-tag slot="reference" size="small" type="danger" class="reason">
-                <span>审核未通过</span>
-                <span class="el-icon-question status danger" />
-              </el-tag>
-            </el-popover>
-            <!-- 未通过原因展示END -->
-          </template>
+          <audit-status :status="row.shopAuditStatus" :reason="row.invalidReason" />
         </template>
       </el-table-column>
       <el-table-column label="审核人" align="center" width="200px">
@@ -90,13 +78,7 @@
     </el-table>
     <!-- 表格区域END -->
     <!-- 页码 -->
-    <pagination
-      v-show="total > 0"
-      :total="total"
-      :page.sync="listQuery.pageNum"
-      :limit.sync="listQuery.pageSize"
-      @pagination="getList"
-    />
+    <pagination :total="total" :page.sync="listQuery.pageNum" :limit.sync="listQuery.pageSize" @pagination="getList" />
     <!-- 审核弹窗 -->
     <el-dialog title="授权机构审核" :visible.sync="dialogVisible" width="450px" @close="dialogClosed">
       <div class="auth-info">

+ 1 - 15
src/views/normal/audit/club/components/device-list.vue

@@ -31,19 +31,7 @@
       <el-table-column prop="snCode" label="设备SN码" align="center" />
       <el-table-column label="审核状态" width="120px" align="center">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.shopAuditStatus === 2" size="small" type="warning">待审核</el-tag>
-          <el-tag v-if="row.shopAuditStatus === 1" size="small" type="success">审核通过</el-tag>
-          <!-- 未通过原因展示 -->
-          <template v-if="row.shopAuditStatus === 0">
-            <!-- <span class="status danger">审核未通过&nbsp;</span> -->
-            <el-popover placement="top-start" title="审核说明" width="400" trigger="hover" :content="row.invalidReason">
-              <el-tag slot="reference" size="small" type="danger" class="reason">
-                <span>审核未通过</span>
-                <span class="el-icon-question status danger" />
-              </el-tag>
-            </el-popover>
-            <!-- 未通过原因展示END -->
-          </template>
+          <audit-status :status="row.shopAuditStatus" :reason="row.invalidReason" />
         </template>
       </el-table-column>
       <el-table-column label="审核人" align="center">
@@ -69,7 +57,6 @@
           <el-button
             v-if="row.shopAuditStatus !== 1"
             type="primary"
-            icon="el-icon-s-check"
             size="mini"
             @click="$_navigationTo(`/supplier-audit/club/device-detail?id=${row.productId}&authId=${listQuery.authId}`)"
           >审核</el-button>
@@ -80,7 +67,6 @@
     <!-- 表格区域END -->
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 20 - 4
src/views/normal/audit/club/review.vue

@@ -21,7 +21,7 @@
         <div class="row">
           <div class="col">所在位置:</div>
           <div class="col">
-            <div class="map" @click="dialogMapVisible = true">
+            <div class="map" @click="initMap">
               <i class="el-icon-map-location" />
               <span>点击查看</span>
             </div>
@@ -138,18 +138,21 @@
     <!-- 地图坐标拾取 -->
     <el-dialog class="map-dialog" title="地图信息" :visible.sync="dialogMapVisible" width="80%">
       <!-- <location v-if="dialogMapVisible" :init-point="formData.point" @point="handlePointChange" /> -->
-      <map-ui :init-point="clubInfo.lngAndLat" />
+      <!-- <map-ui :init-point="clubInfo.lngAndLat" /> -->
+      <a-map ref="aMap" :lnglat="lnglat" />
     </el-dialog>
   </div>
 </template>
 
 <script>
 import AMapUI from '@/components/AMapUI'
+import SimpleAMap from '@/components/SimpleAMap'
 import { getAuthFormData, auditAuth } from '@/api/auth'
 import { mapGetters } from 'vuex'
 export default {
   components: {
-    [AMapUI.name]: AMapUI
+    [AMapUI.name]: AMapUI,
+    [SimpleAMap.name]: SimpleAMap
   },
   data() {
     return {
@@ -206,13 +209,26 @@ export default {
     }
   },
   computed: {
-    ...mapGetters(['authUserId'])
+    ...mapGetters(['authUserId']),
+    // 位置坐标
+    lnglat() {
+      return this.clubInfo.lngAndLat ? this.clubInfo.lngAndLat.split(',') : null
+    }
   },
   created() {
     this.auditForm.authId = this.$route.query.authId
     this.getDetail()
   },
   methods: {
+    // 地图定位
+    initMap() {
+      this.dialogMapVisible = true
+      if (this.lnglat) {
+        this.$nextTick(() => {
+          this.$refs.aMap.init()
+        })
+      }
+    },
     // 数据回显
     getDetail() {
       getAuthFormData({ authId: this.auditForm.authId }).then((res) => {

+ 0 - 1
src/views/normal/club/device-cate.vue

@@ -96,7 +96,6 @@
 
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 29 - 1
src/views/normal/club/device/edit.vue

@@ -45,9 +45,36 @@
         <el-input v-model="formData.productImage" class="hiddenInput" />
       </el-form-item>
        -->
+
+      <!-- **************** 新方法配置授权牌 START ******************* -->
+      <!-- <el-form-item label="授权牌:">
+        <el-radio-group v-model="formData.addQrCodeFlag" size="mini">
+          <el-radio :label="0" border>模板库生成</el-radio>
+          <el-radio :label="1" border>自定义上传</el-radio>
+        </el-radio-group>
+        <div style="margin-top: 12px">
+
+          <template v-if="formData.addQrCodeFlag === 1">
+            <upload-image
+              tip="建议尺寸:150px * 112px"
+              :image-list="certificateImageList"
+              :before-upload="beforeCertificateImageUpload"
+              @success="uploadCertificateImageSuccess"
+              @remove="handleCertificateImageRemove"
+            />
+            <el-input v-model="formData.certificateImage" class="hiddenInput" />
+          </template>
+          <el-image v-else style="width:148px;height:148px" />
+        </div>
+      </el-form-item> -->
+
+      <!-- **************** 新方法配置授权牌 End ******************* -->
+
+      <!-- **************** 旧方法配置授权牌 START ******************* -->
+      <!-- 上传授权牌 -->
       <el-form-item label="授权牌:" prop="certificateImage">
         <upload-image
-          tip="建议尺寸:150px * 112px"
+          tip="建议尺寸:542px * 546px"
           :image-list="certificateImageList"
           :before-upload="beforeCertificateImageUpload"
           @success="uploadCertificateImageSuccess"
@@ -66,6 +93,7 @@
       <el-form-item v-if="formData.addQrCodeFlag === 1" label="选择模板:">
         <auth-card-template v-model="formData.addTemplateType" :image-list="certificateImageList" />
       </el-form-item>
+      <!-- **************** 旧方法配置授权牌 END ******************* -->
 
       <el-form-item label="购买渠道:">
         <el-input v-model="formData.purchaseWay" placeholder="请输入购买渠道" />

+ 0 - 1
src/views/normal/club/device/index.vue

@@ -117,7 +117,6 @@
 
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 210 - 14
src/views/normal/club/edit.vue

@@ -26,12 +26,20 @@
           placeholder="请输入经纬度 (格式:纬度,经度,可通过右侧地图小按钮获取)"
           clearable
         >
-          <el-button slot="append" icon="el-icon-map-location" @click="dialogMapVisible = true" />
+          <el-button slot="append" icon="el-icon-map-location" @click="initMap" />
         </el-input>
       </el-form-item>
       <el-form-item label="联系电话:" prop="mobile">
         <el-input v-model="formData.mobile" placeholder="请输入联系方式" clearable />
       </el-form-item>
+
+      <el-form-item label="认证编号:" prop="authCode">
+        <el-input v-model="formData.authCode" placeholder="请输认证编号" clearable />
+      </el-form-item>
+
+      <el-form-item label="认证日期:" prop="authDate">
+        <el-date-picker v-model="formData.authDate" type="date" placeholder="选择日期" style="width: 100%" />
+      </el-form-item>
       <!-- <el-form-item label="手机号:" prop="userMobile">
         <el-input v-model="formData.userMobile" placeholder="请输入手机号" clearable maxlength="11" show-word-limit />
       </el-form-item> -->
@@ -46,6 +54,7 @@
         />
       </el-form-item>
       <el-form-item label="门头照:" prop="banner">
+        <div class="form-label-tip">至少上传一张机构门店图,最多上传6张)</div>
         <el-input v-show="false" v-model="formData.banner" />
         <upload-image
           tip="至少上传一张,最多6张;建议尺寸:542px * 542px"
@@ -57,6 +66,50 @@
         />
       </el-form-item>
 
+      <!-- **************** 新方法配置授权牌 START ******************* -->
+      <el-form-item label="授权牌:">
+        <el-radio-group v-model="formData.authImageType" size="mini">
+          <el-radio :label="1" border>模板库生成</el-radio>
+          <el-radio :label="2" border>自定义上传</el-radio>
+        </el-radio-group>
+        <div style="margin-top: 12px">
+          <template v-if="formData.authImageType === 2">
+            <upload-image
+              tip="建议尺寸:542px * 546px"
+              :image-list="authImageList"
+              :before-upload="beforeAuthImageUpload"
+              @success="uploadAuthImageSuccess"
+              @remove="handleAuthImageRemove"
+            />
+            <el-input v-show="false" v-model="formData.authImage" />
+          </template>
+          <template v-else>
+            <el-image
+              v-if="formData.authImage"
+              style="width: 148px; height: 148px"
+              :src="formData.authImage"
+              :preview-src-list="[formData.authImage]"
+            />
+          </template>
+        </div>
+      </el-form-item>
+
+      <el-form-item v-if="formData.authImageType === 1" label="授权牌logo:">
+        <div class="form-label-tip">授权牌logo(提示:授权牌logo与机构名称组合)</div>
+        <div style="margin-top: 8px">
+          <upload-image
+            :tip="authImageLogoUploadTip"
+            :image-list="authImageLogoList"
+            :before-upload="beforeAuthImageLogoUpload"
+            @success="uploadAuthImageLogoSuccess"
+            @remove="handleAuthImageLogoRemove"
+          />
+          <el-input v-show="false" v-model="formData.authImageLogo" />
+        </div>
+      </el-form-item>
+
+      <!-- **************** 新方法配置授权牌 End ******************* -->
+
       <el-form-item label="机构类型:">
         <el-radio-group v-model="formData.firstClubType">
           <el-radio :label="1">医美</el-radio>
@@ -128,7 +181,8 @@
       width="80%"
     >
       <!-- <location v-if="dialogMapVisible" :init-point="formData.point" @point="handlePointChange" /> -->
-      <map-ui v-if="dialogMapVisible" :init-point="formData.point" :address="locationAddress" @change="markerChange" />
+      <!-- <map-ui v-if="dialogMapVisible" :init-point="formData.point" :address="locationAddress" @change="markerChange" /> -->
+      <a-map ref="aMap" :lnglat="lnglat" :address="locationAddress" @position="onPosition" />
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" size="mini" @click="dialogMapVisible = false">确 定</el-button>
       </div>
@@ -139,16 +193,20 @@
 <script>
 // import Location from '@/components/location'
 import AMapUI from '@/components/AMapUI'
+import SimpleAMap from '@/components/SimpleAMap'
 import UploadImage from '@/components/UploadImage'
 import { mapGetters } from 'vuex'
 import { saveBrandAuth, getAuthFormData } from '@/api/auth'
 import { getAddress } from '@/api/common'
 import { isPoint, isMobile, isNumber } from '@/utils/validate'
+import { formatDate } from '@/utils'
+import { authTempUsed } from '@/api/system'
 
 export default {
   components: {
     // Location
     [AMapUI.name]: AMapUI,
+    [SimpleAMap.name]: SimpleAMap,
     UploadImage
   },
   data() {
@@ -209,7 +267,13 @@ export default {
         empNum: '',
         firstClubType: 1,
         secondClubType: 1,
-        medicalLicenseImage: ''
+        medicalLicenseImage: '',
+        // 新增授权牌字段
+        authCode: '',
+        authDate: '',
+        authImageType: '',
+        authImageLogo: '',
+        authImage: ''
       },
       rules: {
         name: [{ required: true, message: '机构名称不能为空', trigger: ['blur', 'change'] }],
@@ -222,7 +286,8 @@ export default {
         remarks: [{ required: true, message: '店铺备注不能为空', trigger: 'blur' }],
         medicalLicenseImage: [{ required: true, message: '请上传医疗许可证', trigger: 'change' }],
         empNum: [{ required: true, message: '员工人数不能为空', trigger: 'change' }],
-        userMobile: [{ validator: validatePhoneNumber, trigger: 'change' }]
+        userMobile: [{ validator: validatePhoneNumber, trigger: 'change' }],
+        authImageLogo: [{ required: true, message: '请上传授权牌logo', trigger: 'change' }]
       },
       // logo图片列表
       logoList: [],
@@ -231,7 +296,16 @@ export default {
       // 级联选择的地址
       address: '',
       // 医疗许可证图片
-      licenseImageList: []
+      licenseImageList: [],
+      // 授权牌照图片列表
+      authImageList: [],
+      // 授权牌logo列表
+      authImageLogoList: [],
+      // 验证
+      validatorFields: {
+        authImageLogoWidth: 100,
+        authImageLogoHeight: 100
+      }
     }
   },
   computed: {
@@ -256,15 +330,38 @@ export default {
     },
     // 定位使用的地址
     locationAddress() {
+      // 广东省/深圳市/福田区景峰大厦
       return this.address + this.formData.fullAddress
+    },
+    // 位置坐标
+    lnglat() {
+      return this.formData.point ? this.formData.point.split(',') : null
+    },
+    // 授权牌logo上传提示
+    authImageLogoUploadTip() {
+      return `限制尺寸:${this.validatorFields.authImageLogoWidth}px *${this.validatorFields.authImageLogoHeight}px`
     }
   },
   created() {
     this.editType = this.$route.query.type || 'add'
     this.authId = this.$route.query.id
     this.initFormData()
+    this.fetchAuthTempUsed()
   },
   methods: {
+    // 地图定位
+    initMap() {
+      this.dialogMapVisible = true
+      this.$nextTick(() => {
+        this.$refs.aMap.init()
+      })
+    },
+
+    // 获取位置坐标
+    onPosition(lnglat) {
+      this.formData.point = `${lnglat.lng},${lnglat.lat}`
+    },
+
     // 自定义属性修改
     custromizeFormChange(data) {
       this.customValue = data.name
@@ -299,8 +396,13 @@ export default {
         this.formData.customFlag = res.data.customFlag
         this.formData.remarks = res.data.remarks
 
-        this.logoList = [{ name: '', url: res.data.logo }]
-        this.bannerList = res.data.bannerList.map((item) => ({ name: '', url: item }))
+        if (res.data.logo) {
+          this.logoList = [{ name: '机构logo', url: res.data.logo }]
+        }
+
+        if (res.data.bannerList.length > 0) {
+          this.bannerList = res.data.bannerList.map((item, index) => ({ name: `门头照${index}`, url: item }))
+        }
 
         this.formData.address = [res.data.provinceId, res.data.cityId, res.data.townId]
         // this.formData.address = '广东省/深圳市/福田区'
@@ -310,11 +412,28 @@ export default {
         this.formData.empNum = res.data.empNum
         this.formData.firstClubType = res.data.firstClubType
         this.formData.secondClubType = res.data.secondClubType
+
         this.formData.medicalLicenseImage = res.data.medicalLicenseImage
+        if (res.data.medicalLicenseImage) {
+          this.licenseImageList = [{ name: '医疗许可证', url: res.data.medicalLicenseImage }]
+        }
 
         this.formData.userMobile = res.data.userMobile
 
-        this.licenseImageList = [{ name: '', url: res.data.medicalLicenseImage }]
+        // 授权牌相关字段
+        this.formData.authCode = res.data.authCode
+        this.formData.authDate = res.data.authDate
+        this.formData.authImageType = res.data.authImageType
+
+        this.formData.authImageLogo = res.data.authImageLogo
+        if (res.data.authImageLogo) {
+          this.authImageLogoList = [{ name: '授权牌logo', url: res.data.authImageLogo }]
+        }
+
+        this.formData.authImage = res.data.authImage
+        if (res.data.authImage) {
+          this.authImageList = [{ name: '自定义授权牌', url: res.data.authImage }]
+        }
       })
     },
 
@@ -336,7 +455,12 @@ export default {
           firstClubType,
           secondClubType,
           medicalLicenseImage,
-          userMobile
+          userMobile,
+          authCode,
+          authDate,
+          authImageType,
+          authImageLogo,
+          authImage
         } = this.formData
 
         const authUserId = this.proxyInfo?.authUserId || this.authUserId
@@ -359,11 +483,17 @@ export default {
           firstClubType,
           secondClubType,
           medicalLicenseImage,
-          userMobile
+          userMobile,
+          authCode,
+          authDate: authDate ? formatDate(authDate, 'yyyy.MM.DD') : '',
+          authImageType,
+          authImageLogo,
+          authImage
         }
 
         data.bannerList = this.bannerList.map((item) => (item.response ? item.response.data : item.url))
-
+        console.log(data)
+        // return
         saveBrandAuth(data)
           .then((res) => {
             const h = this.$createElement
@@ -372,12 +502,12 @@ export default {
               message: h('i', { style: 'color: #333' }, `已修改授权机构:"${this.formData.name}"`),
               duration: 3000
             })
-            this.$refs.submitForm.resetFields()
+            // this.$refs.submitForm.resetFields()
             this.$store.dispatch('tagsView/delView', this.$route)
             this.$router.push('/club/list')
           })
           .catch((err) => {
-            this.$message.danger(err.msg)
+            console.log(err)
           })
       })
     },
@@ -386,6 +516,25 @@ export default {
       if (node.length <= 0) return
       this.address = node[0].pathLabels.join()
     },
+
+    // 获取当前机构可用授权牌模板
+    async fetchAuthTempUsed() {
+      try {
+        const res = await authTempUsed({
+          authUserId: this.authUserId,
+          authFlag: 1,
+          status: 1
+        })
+        if (res.data) {
+          const [width, height] = res.data.logoSize.split(',')
+          this.validatorFields.authImageLogoWidth = width
+          this.validatorFields.authImageLogoHeight = height
+        }
+      } catch (error) {
+        console.log(error)
+      }
+    },
+
     // logo上传
     uploadLogoSuccess({ response, file, fileList }) {
       this.logoList = fileList
@@ -437,6 +586,54 @@ export default {
         this.$message.error('医疗许可证图片大小不能超过 1MB!')
       }
       return flag
+    },
+
+    // 授权牌照上传
+    beforeAuthImageUpload(file) {
+      const flag = file.size / 1024 / 1024 < 5
+      if (!flag) {
+        this.$message.error('上传授权牌图片大小不能超过 5MB!')
+      }
+      return flag
+    },
+    uploadAuthImageSuccess({ response, file, fileList }) {
+      this.authImageList = fileList
+      this.formData.authImage = response.data
+    },
+    handleAuthImageRemove({ file, fileList }) {
+      this.authImageList = fileList
+      this.formData.authImage = ''
+    },
+
+    // 授权牌logo上传
+    beforeAuthImageLogoUpload(file) {
+      return new Promise((resolve, reject) => {
+        if (file.size > 5 * 1024 * 1024) {
+          this.$message.error('授权牌logo图片大小不能超过 5MB!')
+          reject('图片大小超出最大限制')
+        }
+        const image = new Image()
+        image.src = URL.createObjectURL(file)
+        image.onload = (e) => {
+          const { path } = e
+          const { naturalWidth, naturalHeight } = path[0]
+          const { authImageLogoWidth: width, authImageLogoHeight: height } = this.validatorFields
+          if (naturalWidth > width || naturalHeight > height) {
+            this.$message.error('图片尺寸校验未通过')
+            reject('图片尺寸校验未通过')
+          } else {
+            resolve('图片尺寸校验通过')
+          }
+        }
+      })
+    },
+    uploadAuthImageLogoSuccess({ response, file, fileList }) {
+      this.authImageLogoList = fileList
+      this.formData.authImageLogo = response.data
+    },
+    handleAuthImageLogoRemove({ file, fileList }) {
+      this.authImageLogoList = fileList
+      this.formData.authImageLogo = ''
     }
   }
 }
@@ -463,7 +660,6 @@ export default {
     width: 140px;
   }
 }
-
 .attributes {
   padding-top: 16px;
 }

+ 0 - 1
src/views/normal/club/index.vue

@@ -125,7 +125,6 @@
 
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 3 - 3
src/views/normal/club/user/index-temp.vue

@@ -81,13 +81,13 @@
       </el-table-column>
       <el-table-column label="操作" width="200px" align="center">
         <template slot-scope="{row}">
-          <permission-button v-if="row.status === 1" type="danger" size="mini" style="margin-right:5px" @click="handleUnbindGenerate(row)">解绑邀请码</permission-button>
-          <permission-button v-else type="primary" size="mini" style="margin-right:5px" @click="handleUpdateGenerate(row)">更新邀请码</permission-button>
+          <permission-button v-if="row.status === 1" type="danger" size="mini" style="margin-right:12px" @click="handleUnbindGenerate(row)">解绑邀请码</permission-button>
+          <permission-button v-else type="primary" size="mini" style="margin-right:12px" @click="handleUpdateGenerate(row)">更新邀请码</permission-button>
         </template>
       </el-table-column>
     </el-table>
     <!-- 表格区域END -->
-    <pagination v-show="total>0" :total="total" :page.sync="listQuery.pageNum" :limit.sync="listQuery.pageSize" @pagination="getList(listQuery)" />
+    <pagination :total="total" :page.sync="listQuery.pageNum" :limit.sync="listQuery.pageSize" @pagination="getList(listQuery)" />
   </div>
 </template>
 

+ 0 - 1
src/views/normal/club/user/index.vue

@@ -71,7 +71,6 @@
     </el-table>
     <!-- 表格区域END -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 1 - 3
src/views/normal/feedback/index.vue

@@ -99,8 +99,7 @@
           <permission-button
             type="primary"
             size="mini"
-            style="margin-right:5px"
-            icon="el-icon-edit"
+            style="margin-right:12px"
             @click="$_navigationTo(`/feedback/detail?feedbackId=${row.feedbackId}`)"
           >处理</permission-button>
         </template>
@@ -109,7 +108,6 @@
     <!-- 表格区域END -->
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 2 - 3
src/views/normal/material/article/index.vue

@@ -92,13 +92,13 @@
           <permission-button
             type="primary"
             size="mini"
-            style="margin-right:5px"
+            style="margin-right:12px"
             @click="$_navigationTo(`article-edit?articleId=${row.articleId}`)"
           >编辑</permission-button>
           <permission-button
             type="danger"
             size="mini"
-            style="margin-right:5px"
+            style="margin-right:12px"
             @click="handleRemoveArticle(row)"
           >删除</permission-button>
         </template>
@@ -106,7 +106,6 @@
     </el-table>
     <!-- 表格区域END -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 5 - 6
src/views/normal/material/file/index.vue

@@ -89,19 +89,19 @@
           <permission-button
             type="primary"
             size="mini"
-            style="margin-right:5px"
+            style="margin-right:12px"
             @click="handlePreviewFile(row)"
           >预览</permission-button>
           <permission-button
             type="primary"
             size="mini"
-            style="margin-right:5px"
+            style="margin-right:12px"
             @click="handleShowDialog('edit', row)"
           >编辑</permission-button>
           <permission-button
             type="danger"
             size="mini"
-            style="margin-right:5px"
+            style="margin-right:12px"
             @click="handleRemoveFile(row)"
           >删除</permission-button>
         </template>
@@ -109,7 +109,6 @@
     </el-table>
     <!-- 表格区域END -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"
@@ -369,10 +368,10 @@ export default {
 
     // 文件上传之前
     beforeUpload(file, fileList) {
-      let maxSize = 100
+      let maxSize = 500
       // 文件过大
       if (file.size > maxSize * 1024 * 1024) {
-        this.$message.warning('文件大小超过100MB,请重新选择!')
+        this.$message.warning('文件大小超过500MB,请重新选择!')
         return Promise.reject()
       }
       maxSize = 30

+ 2 - 2
src/views/normal/material/image/edit.vue

@@ -103,9 +103,9 @@ export default {
       this.imageList = fileList
     },
     beforeUpload(file, fileList) {
-      const flag = file.size <= 5 * 1024 * 1204
+      const flag = file.size <= 50 * 1024 * 1204
       if (!flag) {
-        this.$message.warning('文件大小不能超过5MB,请重新选择!')
+        this.$message.warning('文件大小不能超过50MB,请重新选择!')
       }
       return flag
     }

+ 0 - 1
src/views/normal/material/image/index.vue

@@ -102,7 +102,6 @@
       </el-table-column>
     </el-table>
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 4 - 5
src/views/normal/material/package/index.vue

@@ -89,13 +89,13 @@
           <permission-button
             type="primary"
             size="mini"
-            style="margin-right:5px"
+            style="margin-right:12px"
             @click="handleShowDialog('edit', row)"
           >编辑</permission-button>
           <permission-button
             type="danger"
             size="mini"
-            style="margin-right:5px"
+            style="margin-right:12px"
             @click="handleRemoveFile(row)"
           >删除</permission-button>
         </template>
@@ -103,7 +103,6 @@
     </el-table>
     <!-- 表格区域END -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"
@@ -365,10 +364,10 @@ export default {
 
     // 文件上传之前
     beforeUpload(file, fileList) {
-      let maxSize = 100
+      let maxSize = 500
       // 文件过大
       if (file.size > maxSize * 1024 * 1024) {
-        this.$message.warning('文件大小超过100MB,请重新选择!')
+        this.$message.warning('文件大小超过500MB,请重新选择!')
         return Promise.reject()
       }
       maxSize = 30

+ 54 - 26
src/views/normal/material/video/index.vue

@@ -53,7 +53,7 @@
             <el-popover placement="top-start" title="审核说明" width="400" trigger="hover" :content="row.invalidReason">
               <el-tag slot="reference" size="small" type="danger" class="reason">
                 <span>审核未通过</span>
-                <span class="el-icon-question status danger " />
+                <span class="el-icon-question status danger" />
               </el-tag>
             </el-popover>
             <!-- 未通过原因展示END -->
@@ -65,17 +65,17 @@
           <!-- 只有审核通过了才能操作上下线 auditStatus :审核状态 -->
           <template v-if="row.auditStatus === 1">
             <template v-if="row.status === 0">
-              <span style="margin-right:10px;" class="status danger">已下线</span>
+              <span style="margin-right: 10px" class="status danger">已下线</span>
               <permission-button type="primary" size="mini" @click="handleChangeStatus(row)">上线</permission-button>
             </template>
             <template v-else>
-              <span style="margin-right:10px;" class="status success ">已上线</span>
+              <span style="margin-right: 10px" class="status success">已上线</span>
               <permission-button type="info" size="mini" plain @click="handleChangeStatus(row)">下线</permission-button>
             </template>
           </template>
           <template v-else>
             <!-- <el-tag type="warning">待上线</el-tag> -->
-            <span style="margin-right:10px;" class="status warning">待上线</span>
+            <span style="margin-right: 10px" class="status warning">待上线</span>
           </template>
         </template>
       </el-table-column>
@@ -89,19 +89,19 @@
           <permission-button
             type="primary"
             size="mini"
-            style="margin-right:5px"
+            style="margin-right: 12px"
             @click="handlePlayer(row)"
           >播放</permission-button>
           <permission-button
             type="primary"
             size="mini"
-            style="margin-right:5px"
+            style="margin-right: 12px"
             @click="handleShowDialog('edit', row)"
           >编辑</permission-button>
           <permission-button
             type="danger"
             size="mini"
-            style="margin-right:5px"
+            style="margin-right: 12px"
             @click="handleRemoveVideo(row)"
           >删除</permission-button>
         </template>
@@ -109,7 +109,6 @@
     </el-table>
     <!-- 表格区域END -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"
@@ -129,8 +128,18 @@
         <el-form-item label="标题:" prop="videoTitle">
           <el-input v-model="dialogData.videoTitle" maxlength="50" show-word-limit />
         </el-form-item>
+        <el-form-item label="视频封面" prop="videoImage">
+          <!-- 216 * 132 -->
+          <upload-image
+            tip="建议尺寸比例:432px * 264px"
+            :image-list="videoImageList"
+            @success="handleUploadImageSussces"
+            @remove="handleRemoveImage"
+          />
+          <el-input v-show="false" v-model="dialogData.videoImage" />
+        </el-form-item>
         <el-form-item ref="formVideoUrlRef" label="上传视频:" prop="videoPreviewUrl">
-          <div class="file-upload-box" style="height:40px;">
+          <div class="file-upload-box" style="height: 40px">
             <!-- 上传文件组件 -->
             <el-upload
               ref="uploadRef"
@@ -145,11 +154,11 @@
               :before-upload="beforeUpload"
               :file-list="fileList"
             >
-              <permission-button size="mini" type="primary" style="width:100%">上传视频</permission-button>
+              <permission-button size="mini" type="primary" style="width: 100%">上传视频</permission-button>
             </el-upload>
             <el-input v-model="dialogData.videoPreviewUrl" type="hidden" class="hiddenInput" />
           </div>
-          <span style="color:#999;font-size:12px">视频大小不能超过<i style="color:red">*500MB*</i></span>
+          <span style="color: #999; font-size: 12px">视频大小不能超过<i style="color: red">*500MB*</i></span>
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -161,9 +170,7 @@
 
     <!-- 视频预览对话框 -->
     <el-dialog title="视频预览" :visible.sync="dialogPreviewVisible" width="60%" @closed="dialogPreviewColosed">
-      <video :src="videoPreviewUrl" controls="controls" width="100%">
-        您的浏览器不支持播放该视频
-      </video>
+      <video :src="videoPreviewUrl" controls="controls" width="100%">您的浏览器不支持播放该视频</video>
       <div slot="footer" class="dialog-footer">
         <permission-button type="primary" @click="dialogPreviewVisible = false">关闭</permission-button>
       </div>
@@ -174,12 +181,13 @@
 
 <script>
 import PermissionButton from '@/views/components/PermissionButton'
+import UploadImage from '@/components/UploadImage'
 import Pagination from '@/components/Pagination' // secondary package based on el-pagination
 import { mapGetters } from 'vuex'
 import { getToken } from '@/utils/auth'
 import { changeVideoStatus, getVideoList, removeVideo, saveVideo } from '@/api/doc'
 export default {
-  components: { Pagination, PermissionButton },
+  components: { Pagination, PermissionButton, UploadImage },
   data() {
     return {
       dialogPreviewVisible: false,
@@ -210,15 +218,19 @@ export default {
         videoTitle: '',
         // videoUrl: '',
         videoPreviewUrl: '',
-        videoDownloadUrl: ''
+        videoDownloadUrl: '',
+        videoImage: ''
       },
       // dialog中表单字段校验规则
       dialogFormRules: {
         videoTitle: [{ required: true, message: '标题不能为空', trigger: 'blur' }],
-        videoPreviewUrl: [{ required: true, message: '链接不能为空', trigger: ['change', 'blur'] }]
+        videoPreviewUrl: [{ required: true, message: '链接不能为空', trigger: ['change', 'blur'] }],
+        videoImage: [{ required: true, message: '视频封面不能为空', trigger: ['change'] }]
       },
       list: [],
-      videoPreviewUrl: ''
+      videoPreviewUrl: '',
+      // 视频封面
+      videoImageList: []
     }
   },
   computed: {
@@ -252,7 +264,7 @@ export default {
       this.listLoading = true
       this.listQuery.authUserId = this.authUserId
       getVideoList(this.listQuery)
-        .then(res => {
+        .then((res) => {
           if (res.code !== 0) return
           this.list = res.data.list
           this.total = res.data.total
@@ -270,7 +282,7 @@ export default {
         return
       }
       // 对标题字段进行规则校验
-      this.$refs.formRef.validateField('videoTitle', error => {
+      this.$refs.formRef.validateField('videoTitle', (error) => {
         if (!error) {
           /**
            * 新增视频和修改视频
@@ -293,7 +305,7 @@ export default {
     },
     // 保存视频
     save() {
-      this.$refs.formRef.validate(valide => {
+      this.$refs.formRef.validate((valide) => {
         if (!valide) return
         this.dialogData.authUserId = this.authUserId
         // uploadVideoUrl不为空,就代表重新上传了视频,需要为表单中的videoUrl重新赋值,新增时该值也不为空
@@ -302,7 +314,7 @@ export default {
           this.dialogData.videoDownloadUrl = this.downloadUrl
         }
         saveVideo(this.dialogData)
-          .then(res => {
+          .then((res) => {
             console.log(res)
             if (res.code !== 0) return
             this.dialogVisible = false
@@ -328,9 +340,12 @@ export default {
         }
       }
       if (this.dialogData.videoPreviewUrl) {
-        this.fileList.push({ name: row.videoName, url: row.videoPreviewUrl })
+        this.fileList = [{ name: row.videoName, url: row.videoPreviewUrl }]
         this.hasVideo = true
       }
+      if (this.dialogData.videoImage) {
+        this.videoImageList = [{ name: '视频封面', url: row.videoImage }]
+      }
     },
     // 删除视频
     async handleRemoveVideo(row) {
@@ -342,7 +357,7 @@ export default {
         this.$message.info('已取消操作')
       })
       if (text !== 'confirm') return
-      removeVideo({ videoId: row.videoId }).then(res => {
+      removeVideo({ videoId: row.videoId }).then((res) => {
         if (res.code !== 0) return
         this.$message.success(res.data)
         this.getList()
@@ -357,12 +372,14 @@ export default {
     // 对话框关闭的回调
     dialogColosed() {
       this.fileList = []
+      this.videoImageList = []
       this.hasVideo = false
       this.dialogData.videoId = ''
       this.dialogData.authUserId = ''
       this.dialogData.videoTitle = ''
       this.dialogData.videoPreviewUrl = ''
       this.dialogData.videoDownloadUrl = ''
+      this.dialogData.videoImage = ''
       this.chooseNewVideo = false
       this.downloadUrl = ''
       this.previewUrl = ''
@@ -420,7 +437,7 @@ export default {
         status: item.status === 1 ? 0 : 1
       }
       changeVideoStatus(params)
-        .then(res => {
+        .then((res) => {
           // this.$message.success(res.data)
           this.$message({
             message: res.data,
@@ -429,13 +446,24 @@ export default {
           })
           this.getList()
         })
-        .catch(err => {
+        .catch((err) => {
           console.log(err)
         })
         .finally(() => {
           this.listLoading = false
         })
     },
+
+    // 封面图片上传成功
+    handleUploadImageSussces({ response, file, fileList }) {
+      this.videoImageList = fileList
+      this.dialogData.videoImage = response.data
+    },
+    handleRemoveImage({ response, file, fileList }) {
+      this.videoImageList = fileList
+      this.dialogData.videoImage = ''
+    },
+
     indexMethod(index) {
       return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1
     }

+ 0 - 1
src/views/normal/personnel/operate/index.vue

@@ -104,7 +104,6 @@
     </el-table>
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 0 - 1
src/views/normal/personnel/training/index.vue

@@ -104,7 +104,6 @@
     </el-table>
     <!-- 页码 -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

+ 170 - 0
src/views/normal/settings/accounts/edit.vue

@@ -0,0 +1,170 @@
+<template>
+  <div class="app-container menus-edit">
+    <el-form ref="userInfoFormRef" label-width="100px" :model="userInfo" :rules="rules">
+      <!-- <el-form-item label="用户头像:">
+        <el-input v-show="false" v-model="user.avatar" />
+        <upload-image tip="建议尺寸:60 * 60px" />
+      </el-form-item> -->
+      <el-form-item label="登录名:" prop="username">
+        <el-input v-model="userInfo.username" placeholder="登录名" />
+      </el-form-item>
+      <el-form-item v-if="!userInfo.id" label="密码:" prop="password">
+        <el-input v-model="userInfo.password" placeholder="密码" />
+      </el-form-item>
+      <el-form-item label="联系人:">
+        <el-input v-model="userInfo.linkMan" placeholder="联系人" />
+      </el-form-item>
+      <el-form-item label="手机号:" prop="mobile">
+        <el-input v-model="userInfo.mobile" placeholder="手机号" />
+      </el-form-item>
+      <el-form-item label="状态:">
+        <el-radio-group v-model="userInfo.status">
+          <el-radio :label="1">启用</el-radio>
+          <el-radio :label="0">停用</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item label="用户角色:" prop="roleList">
+        <el-checkbox-group v-model="userInfo.roleList">
+          <el-checkbox v-for="item in roleList" :key="item.id" :label="item.id">{{ item.roleName }}</el-checkbox>
+        </el-checkbox-group>
+      </el-form-item>
+      <el-form-item>
+        <!-- 确认 取消 -->
+        <div class="control-box">
+          <el-button type="warning" @click="$_back">返回</el-button>
+          <el-button type="primary" @click="onSubmit">保存</el-button>
+        </div>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import { fetchRoleList, createUser, getUser, updateUser } from '@/api/system'
+import { isMobile } from '@/utils/validate'
+
+export default {
+  data() {
+    // 校验角色
+    const validateRoleList = (rule, value, callback) => {
+      if (value instanceof Array) {
+        if (value.length === 0) {
+          callback(new Error('请至少选择一个角色'))
+        } else {
+          callback()
+        }
+      } else {
+        callback(new Error('角色列表为一个数组'))
+      }
+    }
+    // 校验手机号
+    const validateMobile = (rule, value, callback) => {
+      if (value && isMobile(value)) {
+        callback()
+      } else {
+        callback(new Error('请输入合法的手机号'))
+      }
+    }
+    return {
+      editType: 'add',
+      userInfo: {
+        id: 0,
+        username: '',
+        password: '',
+        linkMan: '',
+        mobile: '',
+        status: 1,
+        roleList: [],
+        roleIds: ''
+      },
+      roleList: [],
+      rules: {
+        username: [
+          { required: true, message: '请输入登录名', trigger: 'blur' },
+          { min: 2, max: 15, message: '长度在 2 到 15 个字符', trigger: 'blur' }
+        ],
+        mobile: [{ validator: validateMobile, trigger: 'blur' }],
+        password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
+        roleList: [{ required: true, validator: validateRoleList, trigger: 'change' }]
+      }
+    }
+  },
+  created() {
+    this.editType = this.$route.query.type
+    this.fetchRoleList()
+    if (this.editType === 'edit') {
+      this.userInfo.id = this.$route.query.id
+      this.fetchUserInfo()
+    }
+  },
+  methods: {
+    // 获取角色列表
+    fetchRoleList() {
+      fetchRoleList().then(res => {
+        this.roleList = [...this.roleList, ...res.data.list]
+      })
+    },
+    // 修改保存用户信息
+    updateUserInfo() {
+      this.userInfo.roleIds = this.userInfo.roleList.join(',')
+      updateUser(this.userInfo.id, this.userInfo).then(res => {
+        this.$message.success('修改用户成功')
+        this.$store.dispatch('tagsView/delView', this.$route)
+        this.$router.back()
+      })
+    },
+    // 保存用户信息
+    createUserInfo() {
+      this.userInfo.roleIds = this.userInfo.roleList.join(',')
+      createUser(this.userInfo).then(res => {
+        this.$message.success('添加用户成功')
+        this.$store.dispatch('tagsView/delView', this.$route)
+        this.$router.back()
+      })
+    },
+    // 提交表单
+    onSubmit() {
+      this.$refs.userInfoFormRef.validate(valide => {
+        if (!valide) return
+        if (this.editType === 'add') {
+          this.createUserInfo()
+        } else {
+          this.updateUserInfo()
+        }
+      })
+    },
+    // 获取用户信息
+    fetchUserInfo() {
+      getUser(this.userInfo.id).then(res => {
+        this.setUserInfo(res.data)
+      })
+    },
+    // 设置用户信息
+    setUserInfo(data) {
+      console.log(data)
+      for (const key in this.userInfo) {
+        if (Object.hasOwnProperty.call(data, key)) {
+          this.userInfo[key] = data[key]
+        }
+      }
+      this.userInfo.roleList = data.roleIds.split(',').map(item => parseInt(item))
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.menus-edit {
+  width: 600px;
+  margin: 0 auto;
+  margin-top: 100px;
+}
+.control-box {
+  margin: 20px 0;
+  text-align: center;
+  .el-button {
+    width: 120px;
+    margin: 0 8px;
+  }
+}
+</style>

+ 118 - 0
src/views/normal/settings/accounts/index.vue

@@ -0,0 +1,118 @@
+<template>
+  <div class="app-container">
+    <!-- 搜索区域START -->
+    <div class="filter-container">
+      <div class="filter-control">
+        <span>启用状态:</span>
+        <el-select
+          v-model="listQuery.status"
+          placeholder="启用状态"
+          clearable
+          style="width: 200px"
+          class="filter-item"
+          @change="getList()"
+        >
+          <el-option label="全部" value="" />
+          <el-option label="已启用" :value="0" />
+          <el-option label="未启用" :value="1" />
+        </el-select>
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" @click="$_navigationTo('accounts/add?type=add')">添加用户</el-button>
+      </div>
+    </div>
+    <!-- 搜索区域END -->
+    <el-table
+      v-loading="listLoading"
+      :data="list"
+      style="width: 100%"
+      border
+      fit
+      class="table-cell"
+      header-row-class-name="tableHeader"
+    >
+      <el-table-column :index="indexMethod" label="序号" type="index" width="80" align="center" />
+      <!-- <el-table-column prop="title" label="头像" align="center" width="60">
+        <template slot-scope="{ row }">
+          <img :src="row.avatar" class="avatar" alt="">
+        </template>
+      </el-table-column> -->
+      <el-table-column prop="username" label="登录名" align="center" />
+      <el-table-column prop="linkMan" label="联系人" align="center" />
+      <el-table-column label="手机号" align="center">
+        <template slot-scope="{row}">
+          <span>{{ row.mobile || '—' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="角色描述" align="center">
+        <template slot-scope="{ row }">
+          <span>{{ row.roleDesc || '—' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="启用状态" align="center" width="100">
+        <template slot-scope="{ row }">
+          <el-switch v-model="row.status" :active-value="1" :inactive-value="0" />
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" width="200">
+        <template slot-scope="{ row }">
+          <el-button type="primary" size="mini" :disabled="!row.id" @click="$_navigationTo(`accounts/edit?type=edit&id=${row.id}`)">编辑</el-button>
+          <el-button type="danger" size="mini" :disabled="!row.id" @click="removeUser(row)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+  </div>
+</template>
+
+<script>
+import { fetchUserList, deleteUser } from '@/api/system'
+export default {
+  data() {
+    return {
+      listLoading: false,
+      listQuery: {
+        status: '',
+        pageSize: 10,
+        pageNum: 1
+      },
+      list: []
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    indexMethod(index) {
+      return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1
+    },
+    // 获取列表
+    getList() {
+      this.listQuery.pageNum = 1
+      this.list = []
+      this.fetchUserList()
+    },
+    // 获取用户列表
+    fetchUserList() {
+      fetchUserList(this.listQuery).then(res => {
+        console.log(res)
+        this.list = [...this.list, ...res.data.list]
+      })
+    },
+    // 删除用户
+    removeUser(row) {
+      deleteUser(row.id).then(res => {
+        this.$message.success('删除用户成功')
+        this.getList()
+      })
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.avatar{
+  display: block;
+  width: 40px;
+  height: 40px;
+}
+</style>

+ 142 - 0
src/views/normal/settings/auth-card/components/supplier-list.vue

@@ -0,0 +1,142 @@
+<template>
+  <div>
+    <div class="filter-container">
+      <div class="filter-control">
+        <span>供应商名称:</span>
+        <el-input
+          v-model="listQuery.shopName"
+          size="mini"
+          placeholder="供应商名称"
+          clearable
+          @keyup.enter.native="fetchSupplierList"
+        />
+      </div>
+      <div class="filter-control">
+        <span>供应商类型:</span>
+        <el-select
+          v-model="listQuery.shopType"
+          placeholder="供应商类型"
+          size="mini"
+          clearable
+          @change="fetchSupplierList"
+        >
+          <el-option label="所有类型" value="" />
+          <el-option label="代理商" :value="2" />
+          <el-option label="品牌方" :value="1" />
+        </el-select>
+      </div>
+      <div class="filter-control">
+        <span>手机号:</span>
+        <el-input
+          v-model="listQuery.mobile"
+          clearable
+          size="mini"
+          placeholder="手机号"
+          @keyup.enter.native="fetchSupplierList"
+        />
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" size="mini" @click="filterSupplierList">查询</el-button>
+      </div>
+    </div>
+    <el-table
+      v-infinite-scroll="onLoad"
+      :data="supplierList"
+      border
+      class="infinite-list hide-table-check-all"
+      style="overflow: auto"
+      :infinite-scroll-delay="300"
+      :infinite-scroll-immediate="false"
+      header-row-class-name="tableHeader"
+      highlight-current-row
+      @row-click="handleSelectSupplier"
+    >
+      >
+      <el-table-column label="选择" width="55" align="center">
+        <template slot-scope="{ row }">
+          <el-radio v-model="selectedAuthUserId" :label="row.authUserId"><span v-show="false">1</span></el-radio>
+        </template>
+      </el-table-column>
+      <el-table-column label="序号" type="index" width="80" align="center" />
+      <el-table-column property="name" label="供应商名称" />
+      <el-table-column label="供应商类型" align="center" width="120">
+        <template slot-scope="{ row }">
+          <span v-if="row.shopType === 1">品牌方</span>
+          <span v-else>代理商</span>
+        </template>
+      </el-table-column>
+      <!-- <el-table-column label="登录账号" align="center">
+        <template slot-scope="{ row }">
+          <span v-if="row.loginAccount">{{ row.loginAccount }}</span>
+          <span v-else>未绑定</span>
+        </template>
+      </el-table-column> -->
+      <el-table-column prop="mobile" label="手机号" align="center" width="160" />
+      <el-table-column prop="linkMan" label="联系人" align="center" />
+    </el-table>
+  </div>
+</template>
+<script>
+import { fetchSupplierList } from '@/api/supplier'
+export default {
+  name: 'SupplierList',
+  data() {
+    return {
+      listQuery: {
+        shopName: '',
+        shopType: '',
+        mobile: '',
+        pageNum: 1,
+        pageSize: 10
+      },
+      supplierList: [],
+      selectedAuthUserId: ''
+    }
+  },
+  created() {
+    this.filterSupplierList()
+  },
+  methods: {
+    // 确认选中的供应商
+    handleSubmitSupplier() {
+      this.dialogTableVisible = false
+      this.currentSupplierList = [this.selectedSupplierInfo]
+    },
+    // 选择供应商
+    handleSelectSupplier(e) {
+      this.selectedAuthUserId = e.authUserId
+      this.selectedSupplierInfo = e
+      this.$emit('selected', e)
+    },
+    // 选择供应商对话框关闭事件
+    handleDialogClosed() {
+      this.listQuery.pageNum = 1
+      this.listQuery.shopName = ''
+      this.listQuery.shopType = ''
+      this.listQuery.mobile = ''
+      this.listQuery.linkMan = ''
+    },
+    // 筛选供应商
+    filterSupplierList() {
+      this.pageNum = 1
+      this.supplierList = []
+      this.fetchSupplierList()
+    },
+    // 获取供应商列表
+    fetchSupplierList() {
+      fetchSupplierList(this.listQuery).then((res) => {
+        console.log(res)
+        this.supplierList = [...this.supplierList, ...res.data.list]
+        this.hasNextPage = res.data.hasNextPage
+        this.total = res.data.total
+      })
+    },
+    onLoad() {
+      if (!this.hasNextPage) return
+      this.listQuery.pageNum++
+      this.fetchSupplierList()
+    }
+  }
+}
+</script>
+<style lang="scss" scoped></style>

+ 227 - 0
src/views/normal/settings/auth-card/index.vue

@@ -0,0 +1,227 @@
+<template>
+  <div class="app-container">
+    <!-- 筛选 -->
+    <!-- <div class="filter-container">
+      <div class="filter-control">
+        <el-button type="primary" :loading="isLoading" @click="authTempUpdate">
+          <span>{{ isLoading ? '正在更新...' : '一键生效' }}</span>
+        </el-button>
+      </div>
+    </div> -->
+    <!-- <div class="tip">提示:请勿频繁更新授权牌模板,如有需要,在更新授权牌模板后点击左上角一键生效按钮即可</div> -->
+
+    <!-- 列表 -->
+    <el-table v-loading="listLoading" style="width: 100%" header-row-class-name="tableHeader" :data="list" border fit>
+      <el-table-column :index="indexMethod" label="序号" type="index" width="80" align="center" />
+      <el-table-column label="授权牌模板" align="center" width="200px">
+        <template slot-scope="{ row }">
+          <!-- <el-tooltip effect="dark" content="点击查看全图" placement="top-start">
+            <el-image :src="row.templateImage" :preview-src-list="[row.templateImage]" fit="cover" />
+          </el-tooltip> -->
+          <el-image :src="row.templateImage" fit="cover" />
+        </template>
+      </el-table-column>
+      <el-table-column label="使用位置" align="center">
+        <template slot-scope="{ row }">
+          <el-radio v-model="row.authFlag" :label="1" @change="onClubAuthTempChange(row)">机构认证</el-radio>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" width="280px">
+        <template slot-scope="{ row }">
+          <el-button type="primary" size="mini" @click="onPreview(row)">查看</el-button>
+          <el-button type="primary" size="mini" @click="onDragQrcode(row)">编辑</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 拖拽选取二维码位置 -->
+    <el-dialog :title="dialogTitle" :visible.sync="dragDialogVisible" :fullscreen="fullscreen" @closed="onDragClose">
+      <drag-layout
+        v-if="dragVisible"
+        :qw="current.qw"
+        :qh="current.qh"
+        :old-x="current.oldX"
+        :old-y="current.oldY"
+        :image="current.templateImage"
+        :size="current.templateSize"
+        :is-drag="isDrag"
+        @confirm="onDragConfirm"
+        @cancel="dragDialogVisible = false"
+      />
+    </el-dialog>
+
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="getList(listQuery)"
+    />
+  </div>
+</template>
+<script>
+import DragLayout from '@/components/DragLayout/index.vue'
+import { authTempSave, authTempUpdate, fetchAuthTempList } from '@/api/system'
+import { mapGetters } from 'vuex'
+
+export default {
+  name: 'NormalSettingsAuthCard',
+  components: {
+    DragLayout
+  },
+  data() {
+    return {
+      isLoading: false,
+      dragDialogVisible: false,
+      dragVisible: false,
+      listLoading: false,
+      listQuery: {
+        listType: 2,
+        authUserId: '',
+        pageSize: 15,
+        pageNum: 1
+      },
+      list: [],
+      total: 0,
+      current: null,
+      dialogTitle: '设置二维码位置',
+      fullscreen: true,
+      isDrag: true
+    }
+  },
+  computed: {
+    ...mapGetters(['authUserId'])
+  },
+  created() {
+    this.listQuery.authUserId = this.authUserId
+    this.getList()
+  },
+  methods: {
+    // 一键生效
+    async authTempUpdate() {
+      this.isLoading = true
+      let notification = null
+      notification = this.$notify({
+        title: '提示',
+        message: `模板生效同步中,请勿重复操作!`,
+        duration: 0
+      })
+      try {
+        const res = await authTempUpdate({ authUserId: this.authUserId })
+        console.log(res)
+        this.$message.success('模板更新成功')
+      } catch (error) {
+        console.log(error)
+        this.$message.error(`生效失败,请重试!`)
+      } finally {
+        notification.close()
+        this.isLoading = false
+      }
+    },
+
+    // 确定二维码坐标
+    async onDragConfirm(e) {
+      if (!this.isDrag) return (this.dragDialogVisible = false)
+      try {
+        await authTempSave({
+          templateId: this.current.templateId,
+          qrPosition: [e.x, e.y].join(',')
+        })
+        this.$message.success('模板修改成功')
+        this.getList()
+        this.dragDialogVisible = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+
+    // 选中模板切换
+    async onClubAuthTempChange(row) {
+      this.list.forEach((item) => {
+        if (item.templateId !== row.templateId) item.authFlag = 0
+      })
+      try {
+        await authTempSave({
+          authUserId: this.authUserId,
+          templateId: row.templateId,
+          authFlag: 1
+        })
+        this.getList()
+        this.$message.success('模板使用成功')
+      } catch (error) {
+        console.log(error)
+      }
+    },
+
+    // 预览图片
+    onPreview(row) {
+      this.fullscreen = false
+      this.dialogTitle = '预览'
+      this.isDrag = false
+      this.onDragQrcode(row)
+    },
+
+    // 编辑二维码
+    onDragQrcode(row) {
+      this.current = row
+      if (row.qrSize) {
+        this.current.qw = parseFloat(row.qrSize)
+        this.current.qh = parseFloat(row.qrSize)
+      }
+      const arrs = row.qrPosition ? row.qrPosition.split(',') : [0, 0]
+      this.current.oldX = parseFloat(arrs[0])
+      this.current.oldY = parseFloat(arrs[1])
+      this.dragDialogVisible = true
+      this.dragVisible = true
+    },
+
+    // 拖拽框关闭
+    onDragClose() {
+      console.log(123)
+      this.fullscreen = true
+      this.dialogTitle = '设置二维码位置'
+      this.isDrag = true
+      this.dragVisible = false
+    },
+
+    // 获取授权牌模板列表
+    getList() {
+      this.list = []
+      this.listQuery.pageNum = 1
+      this.fetchAuthTempList(this.listQuery)
+    },
+
+    // 获取授权牌模板列表
+    async fetchAuthTempList() {
+      this.listLoading = true
+      try {
+        const res = await fetchAuthTempList(this.listQuery)
+        this.list = res.data.list
+        this.total = res.data.total
+        this.listLoading = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+
+    // 表格序号
+    indexMethod(index) {
+      return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.el-image {
+  max-width: 120px;
+  max-height: 30px;
+  display: block;
+  margin: 0 auto;
+}
+
+.tip {
+  margin: 12px 0;
+  font-size: 14px;
+  color: #f56c6c;
+}
+</style>

+ 143 - 0
src/views/normal/settings/roles/edit.vue

@@ -0,0 +1,143 @@
+<template>
+  <div class="app-container roles-edit">
+    <el-form ref="ruleRef" label-width="100px" :model="role" :rules="rules">
+      <el-form-item label="角色名称:" prop="roleName">
+        <el-input v-model="role.roleName" placeholder="角色名称" maxlength="20" />
+      </el-form-item>
+      <el-form-item label="角色描述:" prop="roleDesc">
+        <el-input v-model="role.roleDesc" placeholder="角色描述" maxlength="20" />
+      </el-form-item>
+      <el-form-item label="角色授权:" prop="menuIds">
+        <el-input v-show="false" v-model="role.menuIds" />
+        <el-tree
+          ref="tree"
+          :data="menuTree"
+          show-checkbox
+          default-expand-all
+          node-key="id"
+          highlight-current
+          :props="defaultProps"
+          @check-change="getCheckedKeys"
+        />
+      </el-form-item>
+      <el-form-item>
+        <!-- 确认 取消 -->
+        <div class="control-box">
+          <el-button type="warning" @click="$_back">返回</el-button>
+          <el-button type="primary" @click="handleSubmit">保存</el-button>
+        </div>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import { sysMenuTree, createRole, getRole, updateRole } from '@/api/system'
+export default {
+  data() {
+    return {
+      editType: '',
+      role: {
+        id: '',
+        roleName: '',
+        roleDesc: '',
+        menuIds: ''
+      },
+      rules: {
+        roleName: [{ required: true, message: '角色名称不能为空', trigger: 'blur' }],
+        menuIds: [{ required: true, message: '角色授权不能为空', trigger: 'change' }]
+      },
+      menuTree: [],
+      defaultProps: {
+        children: 'subMenus',
+        label: 'title'
+      }
+    }
+  },
+  created() {
+    this.editType = this.$route.query.type
+    if (this.editType === 'edit') {
+      this.role.id = parseInt(this.$route.query.id)
+      this.fetchRoleInfo()
+    }
+    this.getMenuTree()
+  },
+  methods: {
+    getCheckedNodes() {
+      console.log(this.$refs.tree.getCheckedNodes())
+    },
+    getCheckedKeys() {
+      // console.log(this.$refs.tree.getCheckedNodes(false, true).map(item => item.id))
+      this.role.menuIds = this.$refs.tree.getCheckedNodes(false, true).map(item => item.id).join(',')
+    },
+    // 获取菜单权限列表
+    getMenuTree() {
+      sysMenuTree({ menuType: 1 }).then(res => {
+        this.menuTree = res.data
+      })
+    },
+    // 设置角色信息
+    setRoleInfo(data) {
+      for (const key in this.role) {
+        if (Object.hasOwnProperty.call(this.role, key)) {
+          this.role[key] = data[key]
+        }
+      }
+      console.log(this.role.menuIds.split(','))
+      this.$refs.tree.setCheckedKeys([...this.role.menuIds.split(',')])
+    },
+    // 获取角色信息
+    fetchRoleInfo() {
+      getRole(this.role.id).then(res => {
+        console.log(res.data)
+        this.setRoleInfo(res.data)
+      })
+    },
+    // 修改角色
+    updateRole() {
+      updateRole(this.role.id, this.role).then(res => {
+        console.log(res)
+        this.$message.success('修改角色成功')
+        this.$store.dispatch('tagsView/delView', this.$route)
+        this.$router.back()
+      })
+    },
+    // 创建角色
+    createRole() {
+      createRole(this.role).then(res => {
+        console.log(res)
+        this.$message.success('添加角色成功')
+        this.$store.dispatch('tagsView/delView', this.$route)
+        this.$router.back()
+      })
+    },
+    // 提交
+    handleSubmit() {
+      this.$refs.ruleRef.validate(valide => {
+        if (!valide) return
+        if (this.editType === 'add') {
+          this.createRole()
+        } else {
+          this.updateRole()
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.roles-edit {
+  width: 600px;
+  margin: 0 auto;
+  margin-top: 40px;
+}
+.control-box {
+  margin: 20px 0;
+  text-align: center;
+  .el-button {
+    width: 120px;
+    margin: 0 8px;
+  }
+}
+</style>

+ 107 - 0
src/views/normal/settings/roles/index.vue

@@ -0,0 +1,107 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <div class="filter-control">
+        <el-button type="primary" @click="$_navigationTo('roles/add?type=add')">添加角色</el-button>
+      </div>
+    </div>
+    <!-- 搜索区域END -->
+    <el-table
+      v-loading="listLoading"
+      :data="list"
+      style="width: 100%"
+      border
+      fit
+      class="table-cell"
+      header-row-class-name="tableHeader"
+    >
+      <el-table-column :index="indexMethod" label="序号" type="index" width="80" align="center" />
+      <el-table-column prop="roleName" label="角色名" align="center" />
+      <el-table-column label="角色描述" align="center">
+        <template slot-scope="{ row }">
+          <span v-if="row.roleDesc">{{ row.roleDesc }}</span>
+          <span v-else>—</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建时间" align="center" width="160px">
+        <template slot-scope="{ row }">
+          <span v-if="row.createTime">{{ row.createTime | formatTime }}</span>
+          <span v-else>—</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="更新时间" align="center" width="160px">
+        <template slot-scope="{ row }">
+          <span v-if="row.updateTime">{{ row.updateTime | formatTime }}</span>
+          <span v-else>—</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" width="200">
+        <template slot-scope="{ row }">
+          <el-button type="primary" size="mini" @click="$_navigationTo(`roles/edit?type=edit&id=${row.id}`)">编辑</el-button>
+          <el-button type="danger" size="mini" @click="removeRole(row)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+  </div>
+</template>
+
+<script>
+import { fetchRoleList, deleteRole } from '@/api/system'
+export default {
+  data() {
+    return {
+      listLoading: false,
+      listQuery: {
+        status: '',
+        pageSize: 10,
+        pageNum: 1
+      },
+      list: []
+    }
+  },
+  created() {
+    this.fetchRoleList()
+  },
+  methods: {
+    indexMethod(index) {
+      return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1
+    },
+    getList() {
+      this.list = []
+      this.listQuery.pageNum = 1
+      this.fetchRoleList()
+    },
+    // 获取角色列表
+    fetchRoleList() {
+      fetchRoleList(this.listQuery).then(res => {
+        this.list = [...this.list, ...res.data.list]
+      })
+    },
+    // 删除角色
+    removeRole(row) {
+      this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      })
+        .then(() => {
+          deleteRole(row.id).then(res => {
+            this.$message.success('删除角色成功')
+            this.getList()
+          })
+        })
+        .catch(() => {
+          this.$message.info('已取消删除')
+        })
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.avatar {
+  display: block;
+  width: 40px;
+  height: 40px;
+}
+</style>

+ 0 - 1
src/views/normal/user/index.vue

@@ -91,7 +91,6 @@
     </el-table>
     <!-- 表格区域END -->
     <pagination
-      v-show="total > 0"
       :total="total"
       :page.sync="listQuery.pageNum"
       :limit.sync="listQuery.pageSize"

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels