浏览代码

页面接口调试

喻文俊 3 年之前
父节点
当前提交
cba1f3768b
共有 45 个文件被更改,包括 2498 次插入751 次删除
  1. 4 4
      .env.development
  2. 6 0
      public/index.html
  3. 二进制
      public/location.png
  4. 18 0
      src/api/auth.js
  5. 9 0
      src/api/common.js
  6. 55 0
      src/api/doctor.js
  7. 二进制
      src/assets/img/auth-card-placeholder-01.png
  8. 二进制
      src/assets/img/auth-card-placeholder-02.png
  9. 二进制
      src/assets/img/auth-card-placeholder-03.png
  10. 57 0
      src/common/map.config.js
  11. 9 0
      src/common/mapService.js
  12. 14 0
      src/common/request.js
  13. 132 0
      src/components/AMapUI/index.vue
  14. 103 0
      src/components/UploadImage/index.vue
  15. 37 24
      src/router/modules/review.js
  16. 7 0
      src/router/modules/supplier.js
  17. 10 0
      src/styles/index.scss
  18. 2 2
      src/utils/request.js
  19. 87 0
      src/utils/vue-jsonp.js
  20. 125 93
      src/views/authentic/auth/add.vue
  21. 162 94
      src/views/authentic/auth/edit.vue
  22. 21 1
      src/views/authentic/auth/index.vue
  23. 114 8
      src/views/authentic/components/authCardTemplate.vue
  24. 73 65
      src/views/authentic/components/deviceSection.vue
  25. 94 97
      src/views/authentic/doctor/add.vue
  26. 123 99
      src/views/authentic/doctor/edit.vue
  27. 65 18
      src/views/authentic/doctor/index.vue
  28. 76 16
      src/views/authentic/product/add.vue
  29. 108 18
      src/views/authentic/product/edit.vue
  30. 1 2
      src/views/authentic/product/index.vue
  31. 158 0
      src/views/authentic/review/auth/authDetail.vue
  32. 2 2
      src/views/authentic/review/auth/authList.vue
  33. 3 3
      src/views/authentic/review/auth/shopDetail.vue
  34. 1 2
      src/views/authentic/review/auth/shopList.vue
  35. 0 1
      src/views/authentic/review/doc/articleDetail.vue
  36. 1 1
      src/views/authentic/review/doc/articleList.vue
  37. 1 1
      src/views/authentic/review/doc/imageList.vue
  38. 4 4
      src/views/authentic/review/doc/index.vue
  39. 136 86
      src/views/authentic/review/doctor/doctorDetail.vue
  40. 204 0
      src/views/authentic/review/doctor/doctorList.vue
  41. 108 92
      src/views/authentic/review/doctor/index.vue
  42. 47 9
      src/views/authentic/supplier/add.vue
  43. 47 8
      src/views/authentic/supplier/edit.vue
  44. 273 0
      src/views/authentic/supplier/product/detail.vue
  45. 1 1
      src/views/authentic/supplier/product/index.vue

+ 4 - 4
.env.development

@@ -2,12 +2,12 @@
 ENV = 'development'
 
 # 测试地址 API接口
-VUE_APP_BASE_API = 'https://zplma-b.caimei365.com'
-# VUE_APP_BASE_API = 'http://192.168.2.68:8012'
+# VUE_APP_BASE_API = 'https://zplma-b.caimei365.com'
+VUE_APP_BASE_API = 'http://192.168.2.68:8012'
 
 # 文件上传 API接口地址
-VUE_APP_UPLOAD_API='https://zplma-b.caimei365.com'
-# VUE_APP_UPLOAD_API='http://192.168.2.68:8012'
+# VUE_APP_UPLOAD_API='https://zplma-b.caimei365.com'
+VUE_APP_UPLOAD_API='http://192.168.2.68:8012'
 
 # 二维码生成链接location
 VUE_APP_BASE_SERVER = 'https://www-b.caimei365.com'

+ 6 - 0
public/index.html

@@ -11,6 +11,12 @@
       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'
+      }
+    </script>
+    <script src="https://webapi.amap.com/loader.js"></script>
   </head>
   <body>
     <div id="app"></div>

二进制
public/location.png


+ 18 - 0
src/api/auth.js

@@ -37,6 +37,15 @@ export function saveBrandAuth(data) {
   })
 }
 
+// 获取授权信息
+export function getAuthFormData(params) {
+  return request({
+    url: '/auth/form/data',
+    method: 'get',
+    params
+  })
+}
+
 // 修改授权状态
 export function changeAuthStatus(data) {
   return request({
@@ -126,3 +135,12 @@ export function handleFeedback(data) {
     data
   })
 }
+
+// 一键下载授权牌 / 二维码
+export function exportAd(params) {
+  return request({
+    url: '/download/shop/image',
+    method: 'get',
+    params
+  })
+}

+ 9 - 0
src/api/common.js

@@ -7,3 +7,12 @@ export function getCountry(params) {
     method: 'get'
   })
 }
+
+// 城市行政划分
+export function getAddress(params) {
+  return request({
+    url: '/address/select',
+    method: 'get',
+    params
+  })
+}

+ 55 - 0
src/api/doctor.js

@@ -0,0 +1,55 @@
+import request from '@/utils/request'
+
+// 保存
+export function doctorSave(data) {
+  return request({
+    url: '/doctor/save',
+    method: 'post',
+    data
+  })
+}
+
+// 列表
+export function fetchDoctorList(params) {
+  return request({
+    url: '/doctor/list',
+    method: 'get',
+    params
+  })
+}
+
+// 回显
+export function doctorFormData(params) {
+  return request({
+    url: '/doctor/form/data',
+    method: 'get',
+    params
+  })
+}
+
+// 删除
+export function removeDoctor(data) {
+  return request({
+    url: '/doctor/delete',
+    method: 'post',
+    data
+  })
+}
+
+// 修改状态
+export function doctorStatusChange(data) {
+  return request({
+    url: '/doctor/update/status',
+    method: 'post',
+    data
+  })
+}
+
+// 审核
+export function doctorAudit(data) {
+  return request({
+    url: '/doctor/audit',
+    method: 'post',
+    data
+  })
+}

二进制
src/assets/img/auth-card-placeholder-01.png


二进制
src/assets/img/auth-card-placeholder-02.png


二进制
src/assets/img/auth-card-placeholder-03.png


+ 57 - 0
src/common/map.config.js

@@ -0,0 +1,57 @@
+// 浏览器定位
+export function geoLocation() {
+  return new Promise((resovle, reject) => {
+    const geolocation = new window.AMap.Geolocation({
+      // 是否使用高精度定位,默认:true
+      enableHighAccuracy: true,
+      // 设置定位超时时间,默认:无穷大
+      timeout: 10000,
+      // 定位按钮的停靠位置的偏移量,默认:Pixel(10, 20)
+      buttonOffset: new window.AMap.Pixel(10, 20),
+      //  定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false
+      zoomToAccuracy: true,
+      //  定位按钮的排放位置,  RB表示右下
+      buttonPosition: 'RB'
+    })
+
+    geolocation.getCurrentPosition((status, result) => {
+      if (status === 'complete') {
+        resovle(result.position)
+      } else {
+        reject(result.message)
+      }
+    })
+  })
+}
+
+export function geoCoder(address) {
+  return new Promise((resolve, reject) => {
+    const geocoder = new window.AMap.Geocoder({
+      // city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
+      city: '全国'
+    })
+    console.log(geocoder)
+    geocoder.getLocation(address, function(status, result) {
+      if (status === 'complete' && result.info === 'OK') {
+        resolve(result)
+      } else {
+        reject(false)
+      }
+    })
+  })
+}
+
+export default {
+  key: 'ed0e0c030a16414f2a07cfbe350cb14a', // 申请好的Web端开发者Key,首次调用 load 时必填
+  version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
+  plugins: ['AMap.Geolocation', 'AMap.Geocoder', 'AMap.ToolBar', 'AMap.HawkEye', 'AMap.MapType'], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
+  AMapUI: {
+    // 是否加载 AMapUI,缺省不加载
+    version: '1.1', // AMapUI 版本
+    plugins: ['overlay/SimpleMarker'] // 需要加载的 AMapUI ui插件
+  },
+  Loca: {
+    // 是否加载 Loca, 缺省不加载
+    version: '2.0' // Loca 版本
+  }
+}

+ 9 - 0
src/common/mapService.js

@@ -0,0 +1,9 @@
+import request from './request'
+
+// 地理编码 API 服务地址
+export function geocode(params) {
+  return request({
+    url: '/geocode/geo',
+    params
+  })
+}

+ 14 - 0
src/common/request.js

@@ -0,0 +1,14 @@
+import { jsonp } from '@/utils/vue-jsonp'
+
+const BASE_RUI = 'https://restapi.amap.com/v3'
+const KEY = 'c6d2b16b34bcc45482a8790dc90fe8a9'
+
+const request = options => {
+  return jsonp(`${BASE_RUI}${options.url}`, {
+    key: KEY,
+    output: 'JSON',
+    ...options.params
+  })
+}
+
+export default request

+ 132 - 0
src/components/AMapUI/index.vue

@@ -0,0 +1,132 @@
+<template>
+  <div v-loading="mapLoading" class="map">
+    <div id="container" class="map" />
+  </div>
+
+</template>
+
+<script>
+// 引入高德地图配置
+import mapConfig, { geoLocation } from '@/common/map.config'
+import { geocode } from '@/common/mapService'
+export default {
+  name: 'MapUi',
+  props: {
+    // 城市名称
+    address: {
+      type: String,
+      default: ''
+    },
+    initPoint: {
+      type: String,
+      default: ''
+    }
+  },
+  data() {
+    return {
+      mapLoading: true,
+      AMap: null,
+      map: null,
+      marker: null,
+      position: null
+    }
+  },
+  created() {
+    this.$nextTick(() => {
+      this.init()
+    })
+  },
+  beforeDestroy() {
+    this.AMap = null
+    this.marker = null
+    this.position = null
+    this.map.destroy()
+  },
+  methods: {
+    // 初始化地图
+    async init() {
+      this.AMap = await window.AMapLoader.load(mapConfig)
+      this.map = new this.AMap.Map('container', {
+        zoom: 16, // 设置地图显示的缩放级别
+        center: [116.397428, 39.90923], // 设置地图中心点坐标
+        viewMode: '2D' // 设置地图模式
+      })
+      this.map.setDefaultCursor('pointer')
+      this.addController()
+      // 绑定点击事件
+      this.bindEvent()
+
+      // 初始化地图中心点标记
+      // 1 根据已有坐标定位
+      if (this.initPoint) {
+        const [lng, lat] = this.initPoint.split(',')
+        console.log(this.initPoint.split(','))
+        const position = new this.AMap.LngLat(parseFloat(lng), parseFloat(lat))
+        console.log(position)
+        this.markerTo(position)
+        this.map.setCenter(position)
+        return
+      }
+
+      // 2 根据城市信息定位
+      if (this.address) {
+        // const result = await geoCoder('北京市朝阳区阜荣街10号')
+        const result = await geocode({
+          address: this.address
+        })
+        if (result.geocodes.length > 0) {
+          const [lng, lat] = result.geocodes[0].location.split(',')
+          const position = new this.AMap.LngLat(parseFloat(lng, 8), parseFloat(lat, 8))
+          this.markerTo(position)
+          this.map.setCenter(position)
+          return
+        }
+      }
+
+      // 3 默认浏览器定位
+      const { lng, lat } = await geoLocation()
+      const position = new this.AMap.LngLat(lng, lat)
+      this.markerTo(position)
+      this.map.setCenter(position)
+    },
+
+    // 添加控件
+    addController() {
+      this.map.addControl(new this.AMap.ToolBar())
+      this.map.addControl(new this.AMap.MapType())
+    },
+
+    // 绑定事件
+    bindEvent() {
+      this.map.on('complete', () => {
+        this.mapLoading = false
+      })
+      this.map.on('click', ev => {
+        const { lng, lat } = ev.lnglat
+        this.markerTo(new this.AMap.LngLat(lng, lat))
+      })
+    },
+
+    // 移动点标记
+    markerTo(position) {
+      if (this.marker) this.map.remove(this.marker)
+      // 构造点标记
+      this.marker = new this.AMap.Marker({
+        icon: '/location.png',
+        position: position,
+        offset: new this.AMap.Pixel(-24, -44)
+      })
+      this.map.add(this.marker)
+      this.position = position
+      this.$emit('change', this.position)
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.map{
+  width: 100%;
+  height: 600px;
+}
+</style>

+ 103 - 0
src/components/UploadImage/index.vue

@@ -0,0 +1,103 @@
+<template>
+  <div>
+    <el-upload
+      :class="{ 'el-upload-hidden': !chooseState}"
+      :list-type="listType"
+      :action="action"
+      :headers="headers"
+      :on-success="uploadImageSuccess"
+      :on-remove="handleImageRemove"
+      :before-upload="beforeUpload"
+      :on-error="uploadError"
+      :on-preview="handlePictureCardPreview"
+      :limit="limit"
+      :multiple="multiple"
+      :accept="accept"
+      :file-list="imageList"
+    >
+      <div slot="tip" class="el-upload__tip">{{ tip }}</div>
+      <i slot="default" class="el-icon-plus" />
+    </el-upload>
+    <el-dialog :visible.sync="dialogVisible">
+      <img width="100%" :src="dialogImageUrl">
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+export default {
+  props: {
+    tip: {
+      type: String,
+      default: ''
+    },
+    multiple: {
+      type: Boolean,
+      default: false
+    },
+    limit: {
+      type: Number,
+      default: 1
+    },
+    accept: {
+      type: String,
+      default: '.jpg,.png,.gif'
+    },
+    listType: {
+      type: String,
+      default: 'picture-card'
+    },
+    imageList: {
+      type: Array,
+      default: () => []
+    },
+    uuid: {
+      type: Number,
+      default: 0
+    },
+    beforeUpload: {
+      type: Function,
+      default: () => true
+    }
+  },
+  data() {
+    return {
+      dialogVisible: false,
+      dialogImageUrl: ''
+    }
+  },
+  computed: {
+    ...mapGetters(['token']),
+    chooseState() {
+      return this.imageList.length < this.limit
+    },
+    action() {
+      return process.env.VUE_APP_UPLOAD_API + '/upload/image'
+    },
+    headers() {
+      return {
+        'X-Token': this.token
+      }
+    }
+  },
+  methods: {
+    // 上传成功
+    uploadImageSuccess(response, file, fileList) {
+      this.$emit('success', { response, file, fileList })
+    },
+    // 删除
+    handleImageRemove(file, fileList) {
+      this.$emit('remove', { file, fileList })
+    },
+    // 上传失败
+    uploadError(err, file, fileList) {
+      this.$emit('error', { err, file, fileList })
+    },
+    handlePictureCardPreview(file) {
+      this.dialogImageUrl = file.url
+      this.dialogVisible = true
+    }
+  }
+}
+</script>

+ 37 - 24
src/router/modules/review.js

@@ -6,7 +6,7 @@ const authRoutes = [
   {
     path: 'auth',
     component: () => import('@/views/authentic/review/auth/index'),
-    name: 'ReviewList',
+    name: 'ReviewAuth',
     meta: { title: '机构认证', icon: 'el-icon-menu', roles: ['admin'], noCache: true, id: 27 }
   },
   {
@@ -17,17 +17,24 @@ const authRoutes = [
     meta: { title: '机构认证审核', icon: 'el-icon-menu', roles: ['admin'], noCache: true, id: 28 }
   },
   {
-    path: 'shop-list',
+    path: 'auth-detail',
+    hidden: true,
+    component: () => import('@/views/authentic/review/auth/authDetail'),
+    name: 'ReviewAuthDetail',
+    meta: { title: '机构认证审核详情', icon: 'el-icon-menu', roles: ['admin'], noCache: true, id: 47 }
+  },
+  {
+    path: 'auth-shop-list',
     hidden: true,
     component: () => import('@/views/authentic/review/auth/shopList'),
-    name: 'ShopList',
+    name: 'ReviewAuthShopList',
     meta: { title: '设备审核列表', icon: 'el-icon-menu', roles: ['admin'], noCache: true, id: 29 }
   },
   {
-    path: 'shop-detail',
+    path: 'auth-shop-detail',
     hidden: true,
     component: () => import('@/views/authentic/review/auth/shopDetail'),
-    name: 'ShopDetail',
+    name: 'ReviewAuthShopDetail',
     meta: { title: '设备审核详情', icon: 'el-icon-menu', roles: ['admin'], noCache: true, id: 30 }
   }
 ]
@@ -35,67 +42,74 @@ const authRoutes = [
 // 医师资料审核
 const doctorRoutes = [
   {
-    path: 'doctor-list',
+    path: 'doctor',
     component: () => import('@/views/authentic/review/doctor/index'),
-    name: 'ReviewDoctorList',
+    name: 'ReviewDoctor',
     meta: { title: '医师认证', icon: 'el-icon-menu', roles: ['admin'], noCache: true, id: 45 }
   },
   {
-    path: 'doctor/detail',
+    path: 'doctor-list',
+    hidden: true,
+    component: () => import('@/views/authentic/review/doctor/doctorList'),
+    name: 'ReviewDoctorList',
+    meta: { title: '医师审核列表', icon: 'el-icon-menu', roles: ['admin'], noCache: true, id: 46 }
+  },
+  {
+    path: 'doctor-detail',
     hidden: true,
     component: () => import('@/views/authentic/review/doctor/doctorDetail'),
     name: 'ReviewDoctorDetail',
-    meta: { title: '医师认证', icon: 'el-icon-menu', roles: ['admin'], noCache: true, id: 46 }
+    meta: { title: '医师审核详情', icon: 'el-icon-menu', roles: ['admin'], noCache: true, id: 47 }
   }
 ]
 
 // 资料库审核
 const docRoutes = [
   {
-    path: 'doc-list',
+    path: 'doc',
     component: () => import('@/views/authentic/review/doc/index'),
-    name: 'ReviewDocList',
+    name: 'ReviewDoc',
     meta: { title: '资料库', icon: 'el-icon-menu', roles: ['admin'], noCache: true, id: 31 }
   },
   {
-    path: 'article',
+    path: 'doc-article-list',
     component: () => import('@/views/authentic/review/doc/articleList'),
-    name: 'ReviewDocArticle',
+    name: 'ReviewDocArticleList',
     hidden: true,
     meta: { title: '文章审核列表', icon: 'el-icon-menu', roles: ['admin'], noCache: true, id: 32 }
   },
   {
-    path: 'article/detail',
+    path: 'doc-article-detail',
     component: () => import('@/views/authentic/review/doc/articleDetail'),
     name: 'ReviewDocArticleDetail',
     hidden: true,
     meta: { title: '审核文章', icon: 'el-icon-menu', roles: ['admin'], noCache: true, id: 33 }
   },
   {
-    path: 'image',
+    path: 'doc-image-list',
     component: () => import('@/views/authentic/review/doc/imageList'),
-    name: 'ReviewDocImage',
+    name: 'ReviewDocImageList',
     hidden: true,
     meta: { title: '图片审核列表', icon: 'el-icon-menu', roles: ['admin'], noCache: true, id: 34 }
   },
   {
-    path: 'image/detail',
+    path: 'doc-image-detail',
     component: () => import('@/views/authentic/review/doc/imageDetail'),
     name: 'ReviewDocImageDetail',
     hidden: true,
-    meta: { title: '审核图片', icon: 'el-icon-menu', roles: ['admin'], noCache: true, id: 45 }
+    meta: { title: '审核图片', icon: 'el-icon-menu', roles: ['admin'], noCache: true, id: 35 }
   },
   {
-    path: 'video',
+    path: 'doc-video-list',
     component: () => import('@/views/authentic/review/doc/videoList'),
-    name: 'ReviewDocVideo',
+    name: 'ReviewDocVideoList',
     hidden: true,
     meta: { title: '视频审核列表', icon: 'el-icon-menu', roles: ['admin'], noCache: true, id: 36 }
   },
   {
-    path: 'file',
+    path: 'doc-file-list',
     component: () => import('@/views/authentic/review/doc/fileList'),
-    name: 'ReviewDocFile',
+    name: 'ReviewDocFileList',
     hidden: true,
     meta: { title: '文件审核列表', icon: 'el-icon-menu', roles: ['admin'], noCache: true, id: 37 }
   }
@@ -103,12 +117,11 @@ const docRoutes = [
 
 // 审核页面路由
 const reviewRoutes = [
-  // 授权机构审核路由
   {
     path: '/review',
     component: Layout,
     alwaysShow: true,
-    name: 'ReviewAuth',
+    name: 'Review',
     meta: { title: '审核管理', icon: 'el-icon-s-check', roles: ['admin'], noCache: true, id: 38 },
     children: [...authRoutes, ...doctorRoutes, ...docRoutes]
   }

+ 7 - 0
src/router/modules/supplier.js

@@ -44,6 +44,13 @@ const supplierRoutes = [
         component: () => import('@/views/authentic/supplier/product'),
         name: 'AuthList',
         meta: { title: '查看设备认证', icon: 'el-icon-menu', roles: ['admin'], noCache: true, id: 44 }
+      },
+      {
+        hidden: true,
+        path: 'auth-product-detail',
+        component: () => import('@/views/authentic/supplier/product/detail'),
+        name: 'AuthProductDetail',
+        meta: { title: '设备认证详情', icon: 'el-icon-menu', roles: ['admin'], noCache: true, id: 44 }
       }
     ]
   }

+ 10 - 0
src/styles/index.scss

@@ -289,3 +289,13 @@ aside {
     padding-bottom: 0;
   }
 }
+
+.display {
+  .el-input {
+    input {
+      &::placeholder {
+        color: #606266;
+      }
+    }
+  }
+}

+ 2 - 2
src/utils/request.js

@@ -61,7 +61,7 @@ service.interceptors.response.use(
         router.replace('/login')
       }, 500)
       NProgress.done()
-      return
+      return Promise.reject(res)
       // 返回不成功
     } else if (res.code !== 0) {
       Message({
@@ -70,7 +70,7 @@ service.interceptors.response.use(
         duration: 1500
       })
       NProgress.done()
-      return
+      return Promise.reject(res)
     } else {
       NProgress.done()
       return res

+ 87 - 0
src/utils/vue-jsonp.js

@@ -0,0 +1,87 @@
+/* eslint-disable indent */
+/* eslint-disable no-sequences */
+// eslint-disable-next-line indent
+function e(t, n) {
+  t = t.replace(/=/g, '')
+  var o = []
+  switch (n.constructor) {
+    case String:
+    case Number:
+    case Boolean:
+      o.push(encodeURIComponent(t) + '=' + encodeURIComponent(n))
+      break
+    case Array:
+      n.forEach(function(n) {
+        o = o.concat(e(t + '[]=', n))
+      })
+      break
+    case Object:
+      Object.keys(n).forEach(function(r) {
+        var a = n[r]
+        o = o.concat(e(t + '[' + r + ']', a))
+      })
+  }
+  return o
+}
+function t(e) {
+  var n = []
+  return (
+    e.forEach(function(e) {
+      typeof e === 'string' ? n.push(e) : (n = n.concat(t(e)))
+    }),
+    n
+  )
+}
+/**
+ * Vue Jsonp.
+ * # Carry Your World #
+ *
+ * @author: LancerComet
+ * @license: MIT
+ */ var n = {
+  install: function(e) {
+    e.prototype.$jsonp = o
+  }
+}
+function o(n, o, r) {
+  if ((void 0 === o && (o = {}), typeof n !== 'string')) {
+    throw new Error('[Vue-jsonp] Type of param "url" is not string.')
+  }
+  if (typeof o !== 'object' || !o) throw new Error('[Vue-jsonp] Invalid params, should be an object.')
+  return (
+    (r = typeof r === 'number' ? r : 5e3),
+    new Promise(function(a, c) {
+      var u = typeof o.callbackQuery === 'string' ? o.callbackQuery : 'callback'
+      var i =
+        typeof o.callbackName === 'string'
+          ? o.callbackName
+          : 'jsonp_' + (Math.floor(1e5 * Math.random()) * Date.now()).toString(16)
+      ;(o[u] = i), delete o.callbackQuery, delete o.callbackName
+      var s = []
+      Object.keys(o).forEach(function(t) {
+        s = s.concat(e(t, o[t]))
+      })
+      var l = t(s).join('&')
+      var f = function() {
+        p(), clearTimeout(m), c({ status: 400, statusText: 'Bad Request' })
+      }
+      var p = function() {
+        b.removeEventListener('error', f)
+      }
+      var d = function() {
+        document.body.removeChild(b), delete window[i]
+      }
+      var m = null
+      r > -1 &&
+        (m = setTimeout(function() {
+          p(), d(), c({ statusText: 'Request Timeout', status: 408 })
+        }, r)),
+        (window[i] = function(e) {
+          clearTimeout(m), p(), d(), a(e)
+        })
+      var b = document.createElement('script')
+      b.addEventListener('error', f), (b.src = n + (/\?/.test(n) ? '&' : '?') + l), document.body.appendChild(b)
+    })
+  )
+}
+export { n as VueJsonp, o as jsonp }

+ 125 - 93
src/views/authentic/auth/add.vue

@@ -1,13 +1,15 @@
 <template>
   <div class="club-edit">
-    <el-form class="club-edit-form" label-width="120px" :model="formData" :rules="rules">
+    <el-form ref="submitForm" class="club-edit-form" label-width="120px" :model="formData" :rules="rules">
       <el-form-item label="机构名称:" prop="name">
         <el-input v-model="formData.name" placeholder="请输入机构名称" />
       </el-form-item>
       <el-form-item label="所在地区:" prop="address">
         <el-cascader
-          v-model="value"
-          :options="options"
+          ref="cascader"
+          v-model="formData.address"
+          clearable
+          :props="cascaderProps"
           style="width: 100%"
           placeholder="请选择所在地区"
           @change="handleChange"
@@ -26,40 +28,24 @@
       </el-form-item>
       <el-form-item label="机构logo:" prop="logoImage">
         <el-input v-show="false" v-model="formData.logoImage" />
-        <el-upload
-          :class="{ 'el-upload-hidden': logoList.length >= 1}"
-          :file-list="logoList"
-          list-type="picture-card"
-          :action="action"
-          :headers="headers"
-          :on-success="uploadLogoSuccess"
+        <upload-image
+          tip="建议尺寸:242px * 242px"
+          :image-list="logoList"
           :before-upload="beforeLogoUpload"
-          :on-remove="handleLogoRemove"
-          :limit="1"
-        >
-          <div slot="tip" class="el-upload__tip">建议尺寸:242px * 242px</div>
-          <i slot="default" class="el-icon-plus" />
-        </el-upload>
+          @success="uploadLogoSuccess"
+          @remove="handleLogoRemove"
+        />
       </el-form-item>
       <el-form-item label="轮播图:" prop="banner">
         <el-input v-show="false" v-model="formData.banner" />
-        <el-upload
-          ref="coverUploader"
-          :class="{ 'el-upload-hidden': bannerList.length >= 2}"
-          list-type="picture-card"
-          :action="action"
-          :headers="headers"
-          :on-success="uploadBannerSuccess"
-          :on-remove="handleBannerRemove"
+        <upload-image
+          tip="至少上传一张,最多6张;建议尺寸:542px * 542px"
+          :image-list="bannerList"
           :before-upload="beforeBannerUpload"
-          :limit="2"
-          multiple
-          accept=".jpg,.png,.gif"
-          :file-list="bannerList"
-        >
-          <div slot="tip" class="el-upload__tip">至少上传一张,最多6张;建议尺寸:542px * 542px</div>
-          <i slot="default" class="el-icon-plus" />
-        </el-upload>
+          :limit="6"
+          @success="uploadBannerSuccess"
+          @remove="handleBannerRemove"
+        />
       </el-form-item>
     </el-form>
     <div class="submit-btn">
@@ -67,63 +53,45 @@
       <el-button type="warning" @click="$_back()">返回</el-button>
     </div>
 
-    <el-dialog class="map-dialog" title="坐标拾取(请拖动标记点选取准确位置)" :visible.sync="dialogMapVisible" width="80%">
-      <location v-if="dialogMapVisible" :init-point="formData.point" @point="handlePointChange" />
+    <el-dialog
+      class="map-dialog"
+      title="坐标拾取(请拖动标记点选取准确位置)"
+      :visible.sync="dialogMapVisible"
+      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" />
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" size="mini" @click="dialogMapVisible = false">确 定</el-button>
       </div>
     </el-dialog>
-
   </div>
 </template>
 
 <script>
-import Location from '@/components/location'
+// import Location from '@/components/location'
+import AMapUI from '@/components/AMapUI'
+import UploadImage from '@/components/UploadImage'
 import { mapGetters } from 'vuex'
+import { saveBrandAuth } from '@/api/auth'
+import { getAddress } from '@/api/common'
 export default {
   components: {
-    Location
+    // Location
+    [AMapUI.name]: AMapUI,
+    UploadImage
   },
   data() {
     return {
       dialogMapVisible: false,
       point: {},
       value: [],
-      options: [{
-        value: 'zhinan',
-        label: '指南',
-        children: [{
-          value: 'shejiyuanze',
-          label: '设计原则',
-          children: [{
-            value: 'yizhi',
-            label: '一致'
-          }, {
-            value: 'fankui',
-            label: '反馈'
-          }, {
-            value: 'xiaolv',
-            label: '效率'
-          }, {
-            value: 'kekong',
-            label: '可控'
-          }]
-        }, {
-          value: 'daohang',
-          label: '导航',
-          children: [{
-            value: 'cexiangdaohang',
-            label: '侧向导航'
-          }, {
-            value: 'dingbudaohang',
-            label: '顶部导航'
-          }]
-        }]
-      }],
+      options: [],
+
       disabled: false,
       formData: {
         name: '',
-        address: '',
+        address: [],
         fullAddress: '',
         point: '',
         mobile: '',
@@ -132,50 +100,114 @@ export default {
       },
       rules: {
         name: [{ required: true, message: '机构名称不能为空', trigger: ['blur', 'change'] }],
-        address: [{ required: true, message: '地址不能为空', trigger: 'change' }],
+        address: [{ required: true, message: '地址不能为空', trigger: 'change', type: 'array' }],
         fullAddress: [{ required: true, message: '详细不能为空', trigger: ['blur', 'change'] }],
         point: [{ required: true, message: '地址坐标不能为空', trigger: ['blur', 'change'] }],
         mobile: [{ required: true, message: '联系方式不能为空', trigger: ['blur', 'change'] }],
         logoImage: [{ required: true, message: '请上传机构logo', trigger: 'change' }],
         banner: [{ required: true, message: '请至少上传一张banner图片', trigger: 'change' }]
-
       },
       // logo图片列表
       logoList: [],
       // banner图片列表
-      bannerList: []
+      bannerList: [],
+      // 级联选择的地址
+      address: ''
     }
   },
   computed: {
-    ...mapGetters(['token']),
-    // 图片上传
-    action() {
-      return process.env.VUE_APP_UPLOAD_API + '/upload/image'
-    },
-    headers() {
+    ...mapGetters(['authUserId', 'proxyInfo']),
+    // 级联选择器
+    cascaderProps() {
       return {
-        'X-Token': this.token
+        lazy: true,
+        lazyLoad: async(node, resolve) => {
+          const { level, value = 0 } = node
+          const result = await getAddress({ parentId: value, type: level })
+          const nodes = result.data.map(item => ({ value: item.id, label: item.name, leaf: level >= 2 }))
+          resolve(nodes)
+        }
       }
+    },
+    // 定位使用的地址
+    locationAddress() {
+      return this.address + this.formData.fullAddress
     }
   },
   created() {
-
   },
   methods: {
-    handlePointChange(point) {
-      console.log(point)
-      this.formData.point = `${point.lat},${point.lng}`
+    // 获取地址
+    initAddress() {
+      return getAddress({
+        parentId: 19,
+        type: 1
+      })
+    },
+
+    // 地图标记变化
+    markerChange(point) {
+      this.formData.point = `${point.lng},${point.lat}`
+    },
+    submit() {
+      this.$refs.submitForm.validate(valide => {
+        if (!valide) return
+
+        console.log(this.formData)
+        const {
+          name: authParty,
+          address: [provinceId, cityId, townId],
+          mobile,
+          logoImage: logo,
+          point: lngAndLat
+        } = this.formData
+
+        const authUserId = this.proxyInfo?.authUserId || this.authUserId
+
+        const data = {
+          authParty,
+          authUserId,
+          createBy: authUserId,
+          provinceId,
+          cityId,
+          townId,
+          address: this.formData.fullAddress,
+          mobile,
+          logo,
+          lngAndLat
+        }
+
+        data.bannerList = this.bannerList.map(item => item.response.data)
+
+        console.log(data)
+        saveBrandAuth(data)
+          .then(res => {
+            const h = this.$createElement
+            this.$notify.success({
+              title: `添加授权机构`,
+              message: h('i', { style: 'color: #333' }, `已添加授权机构:"${this.formData.name}"`),
+              duration: 3000
+            })
+            this.$refs.submitForm.resetFields()
+            this.$store.dispatch('tagsView/delView', this.$route)
+            this.$router.push('/auth/list')
+          })
+          .catch(err => {
+            this.$message.danger(err.msg)
+          })
+      })
     },
-    submit() {},
     handleChange(e) {
-      console.log(e)
+      const node = this.$refs.cascader.getCheckedNodes()
+      if (node.length <= 0) return
+      this.address = node[0].pathLabels.join()
     },
     // logo上传
-    uploadLogoSuccess(response, file, fileList) {
+    uploadLogoSuccess({ response, file, fileList }) {
       this.logoList = fileList
       this.formData.logoImage = fileList[0].response.data
     },
-    handleLogoRemove(file, fileList) {
+    handleLogoRemove({ file, fileList }) {
       this.logoList = fileList
       this.formData.logoImage = ''
     },
@@ -188,12 +220,14 @@ export default {
     },
 
     // banner上传
-    uploadBannerSuccess(response, file, fileList) {
+    uploadBannerSuccess({ response, file, fileList }) {
       this.bannerList = fileList
       console.log(this.bannerList)
+      this.formData.banner = fileList.length > 0 ? fileList.length : ''
     },
-    handleBannerRemove(file, fileList) {
+    handleBannerRemove({ file, fileList }) {
       this.bannerList = fileList
+      this.formData.banner = fileList.length > 0 ? fileList.length : ''
     },
     beforeBannerUpload(file) {
       const flag = file.size / 1024 / 1024 < 1
@@ -207,13 +241,12 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-
-#allmap{
+#allmap {
   width: 100%;
   height: 600px;
 }
 
-.club-edit{
+.club-edit {
   margin-bottom: 80px;
 }
 
@@ -228,5 +261,4 @@ export default {
     width: 140px;
   }
 }
-
 </style>

+ 162 - 94
src/views/authentic/auth/edit.vue

@@ -1,15 +1,18 @@
 <template>
   <div class="club-edit">
-    <el-form class="club-edit-form" label-width="120px" :model="formData" :rules="rules">
+    <el-form ref="submitForm" class="club-edit-form" label-width="120px" :model="formData" :rules="rules">
       <el-form-item label="机构名称:" prop="name">
         <el-input v-model="formData.name" placeholder="请输入机构名称" />
       </el-form-item>
       <el-form-item label="所在地区:" prop="address">
         <el-cascader
-          v-model="value"
-          :options="options"
+          ref="cascader"
+          v-model="formData.address"
+          :class="{ display: cascaderDisplay }"
+          clearable
+          :props="cascaderProps"
           style="width: 100%"
-          placeholder="请选择所在地区"
+          :placeholder="cascaderPlaceholder"
           @change="handleChange"
         />
       </el-form-item>
@@ -26,40 +29,24 @@
       </el-form-item>
       <el-form-item label="机构logo:" prop="logoImage">
         <el-input v-show="false" v-model="formData.logoImage" />
-        <el-upload
-          :class="{ 'el-upload-hidden': logoList.length >= 1}"
-          :file-list="logoList"
-          list-type="picture-card"
-          :action="action"
-          :headers="headers"
-          :on-success="uploadLogoSuccess"
+        <upload-image
+          tip="建议尺寸:242px * 242px"
+          :image-list="logoList"
           :before-upload="beforeLogoUpload"
-          :on-remove="handleLogoRemove"
-          :limit="1"
-        >
-          <div slot="tip" class="el-upload__tip">建议尺寸:242px * 242px</div>
-          <i slot="default" class="el-icon-plus" />
-        </el-upload>
+          @success="uploadLogoSuccess"
+          @remove="handleLogoRemove"
+        />
       </el-form-item>
       <el-form-item label="轮播图:" prop="banner">
         <el-input v-show="false" v-model="formData.banner" />
-        <el-upload
-          ref="coverUploader"
-          :class="{ 'el-upload-hidden': bannerList.length >= 2}"
-          list-type="picture-card"
-          :action="action"
-          :headers="headers"
-          :on-success="uploadBannerSuccess"
-          :on-remove="handleBannerRemove"
+        <upload-image
+          tip="至少上传一张,最多6张;建议尺寸:542px * 542px"
+          :image-list="bannerList"
           :before-upload="beforeBannerUpload"
-          :limit="2"
-          multiple
-          accept=".jpg,.png,.gif"
-          :file-list="bannerList"
-        >
-          <div slot="tip" class="el-upload__tip">至少上传一张,最多6张;建议尺寸:542px * 542px</div>
-          <i slot="default" class="el-icon-plus" />
-        </el-upload>
+          :limit="6"
+          @success="uploadBannerSuccess"
+          @remove="handleBannerRemove"
+        />
       </el-form-item>
     </el-form>
     <div class="submit-btn">
@@ -67,63 +54,48 @@
       <el-button type="warning" @click="$_back()">返回</el-button>
     </div>
 
-    <el-dialog class="map-dialog" title="坐标拾取(请拖动标记点选取准确位置)" :visible.sync="dialogMapVisible" width="80%">
-      <location v-if="dialogMapVisible" :init-point="formData.point" @point="handlePointChange" />
+    <el-dialog
+      class="map-dialog"
+      title="坐标拾取(请拖动标记点选取准确位置)"
+      :visible.sync="dialogMapVisible"
+      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" />
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" size="mini" @click="dialogMapVisible = false">确 定</el-button>
       </div>
     </el-dialog>
-
   </div>
 </template>
 
 <script>
-import Location from '@/components/location'
+// import Location from '@/components/location'
+import AMapUI from '@/components/AMapUI'
+import UploadImage from '@/components/UploadImage'
 import { mapGetters } from 'vuex'
+import { saveBrandAuth, getAuthFormData } from '@/api/auth'
+import { getAddress } from '@/api/common'
 export default {
   components: {
-    Location
+    // Location
+    [AMapUI.name]: AMapUI,
+    UploadImage
   },
   data() {
     return {
       dialogMapVisible: false,
       point: {},
       value: [],
-      options: [{
-        value: 'zhinan',
-        label: '指南',
-        children: [{
-          value: 'shejiyuanze',
-          label: '设计原则',
-          children: [{
-            value: 'yizhi',
-            label: '一致'
-          }, {
-            value: 'fankui',
-            label: '反馈'
-          }, {
-            value: 'xiaolv',
-            label: '效率'
-          }, {
-            value: 'kekong',
-            label: '可控'
-          }]
-        }, {
-          value: 'daohang',
-          label: '导航',
-          children: [{
-            value: 'cexiangdaohang',
-            label: '侧向导航'
-          }, {
-            value: 'dingbudaohang',
-            label: '顶部导航'
-          }]
-        }]
-      }],
+      options: [],
+
+      authId: '',
       disabled: false,
+
+      area: '',
       formData: {
         name: '',
-        address: '',
+        address: [],
         fullAddress: '',
         point: '',
         mobile: '',
@@ -132,50 +104,146 @@ export default {
       },
       rules: {
         name: [{ required: true, message: '机构名称不能为空', trigger: ['blur', 'change'] }],
-        address: [{ required: true, message: '地址不能为空', trigger: 'change' }],
+        address: [{ required: true, message: '地址不能为空', trigger: 'change', type: 'array' }],
         fullAddress: [{ required: true, message: '详细不能为空', trigger: ['blur', 'change'] }],
         point: [{ required: true, message: '地址坐标不能为空', trigger: ['blur', 'change'] }],
         mobile: [{ required: true, message: '联系方式不能为空', trigger: ['blur', 'change'] }],
         logoImage: [{ required: true, message: '请上传机构logo', trigger: 'change' }],
         banner: [{ required: true, message: '请至少上传一张banner图片', trigger: 'change' }]
-
       },
       // logo图片列表
       logoList: [],
       // banner图片列表
-      bannerList: []
+      bannerList: [],
+      // 级联选择的地址
+      address: ''
     }
   },
   computed: {
-    ...mapGetters(['token']),
-    // 图片上传
-    action() {
-      return process.env.VUE_APP_UPLOAD_API + '/upload/image'
-    },
-    headers() {
+    ...mapGetters(['authUserId', 'proxyInfo']),
+    // 级联选择器
+    cascaderProps() {
       return {
-        'X-Token': this.token
+        lazy: true,
+        lazyLoad: async(node, resolve) => {
+          const { level, value = 0 } = node
+          const result = await getAddress({ parentId: value, type: level })
+          const nodes = result.data.map(item => ({ value: item.id, label: item.name, leaf: level >= 2 }))
+          resolve(nodes)
+        }
       }
+    },
+    cascaderDisplay() {
+      return this.formData.address.length > 0
+    },
+    cascaderPlaceholder() {
+      return this.cascaderDisplay ? this.area : '请选择所在区域'
+    },
+    // 定位使用的地址
+    locationAddress() {
+      return this.address + this.formData.fullAddress
     }
   },
   created() {
-
+    this.authId = this.$route.query.id
+    this.initFormData()
   },
   methods: {
-    handlePointChange(point) {
-      console.log(point)
-      this.formData.point = `${point.lat},${point.lng}`
+    // 获取地址
+    initAddress() {
+      return getAddress({
+        parentId: 19,
+        type: 1
+      })
+    },
+
+    // 地图标记变化
+    markerChange(point) {
+      this.formData.point = `${point.lng},${point.lat}`
+    },
+
+    // 数据回显
+    initFormData() {
+      getAuthFormData({ authId: this.authId }).then(res => {
+        console.log(res)
+        this.formData.name = res.data.authParty
+
+        this.formData.fullAddress = res.data.address
+        this.formData.point = res.data.lngAndLat
+        this.formData.mobile = res.data.mobile
+        this.formData.logoImage = res.data.logo
+        this.formData.banner = res.data.bannerList.length || ''
+
+        this.logoList = [{ name: '', url: res.data.logo }]
+        this.bannerList = res.data.bannerList.map(item => ({ name: '', url: item }))
+
+        this.formData.address = [res.data.provinceId, res.data.cityId, res.data.townId]
+        // this.formData.address = '广东省/深圳市/福田区'
+        this.area = res.data.area
+      })
+    },
+
+    // 表单提交保存
+    submit() {
+      this.$refs.submitForm.validate(valide => {
+        if (!valide) return
+
+        console.log(this.formData)
+        const {
+          name: authParty,
+          address: [provinceId, cityId, townId],
+          mobile,
+          logoImage: logo,
+          point: lngAndLat
+        } = this.formData
+
+        const authUserId = this.proxyInfo?.authUserId || this.authUserId
+
+        const data = {
+          authId: parseInt(this.authId),
+          authParty,
+          authUserId,
+          createBy: authUserId,
+          provinceId,
+          cityId,
+          townId,
+          address: this.formData.fullAddress,
+          mobile,
+          logo,
+          lngAndLat
+        }
+
+        data.bannerList = this.bannerList.map(item => item.response ? item.response.data : item.url)
+
+        console.log(data)
+        saveBrandAuth(data)
+          .then(res => {
+            const h = this.$createElement
+            this.$notify.success({
+              title: `修改授权机构`,
+              message: h('i', { style: 'color: #333' }, `已修改授权机构:"${this.formData.name}"`),
+              duration: 3000
+            })
+            this.$refs.submitForm.resetFields()
+            this.$store.dispatch('tagsView/delView', this.$route)
+            this.$router.push('/auth/list')
+          })
+          .catch(err => {
+            this.$message.danger(err.msg)
+          })
+      })
     },
-    submit() {},
     handleChange(e) {
-      console.log(e)
+      const node = this.$refs.cascader.getCheckedNodes()
+      if (node.length <= 0) return
+      this.address = node[0].pathLabels.join()
     },
     // logo上传
-    uploadLogoSuccess(response, file, fileList) {
+    uploadLogoSuccess({ response, file, fileList }) {
       this.logoList = fileList
       this.formData.logoImage = fileList[0].response.data
     },
-    handleLogoRemove(file, fileList) {
+    handleLogoRemove({ file, fileList }) {
       this.logoList = fileList
       this.formData.logoImage = ''
     },
@@ -188,12 +256,14 @@ export default {
     },
 
     // banner上传
-    uploadBannerSuccess(response, file, fileList) {
+    uploadBannerSuccess({ response, file, fileList }) {
       this.bannerList = fileList
       console.log(this.bannerList)
+      this.formData.banner = fileList.length > 0 ? fileList.length : ''
     },
-    handleBannerRemove(file, fileList) {
+    handleBannerRemove({ file, fileList }) {
       this.bannerList = fileList
+      this.formData.banner = fileList.length > 0 ? fileList.length : ''
     },
     beforeBannerUpload(file) {
       const flag = file.size / 1024 / 1024 < 1
@@ -207,13 +277,12 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-
-#allmap{
+#allmap {
   width: 100%;
   height: 600px;
 }
 
-.club-edit{
+.club-edit {
   margin-bottom: 80px;
 }
 
@@ -228,5 +297,4 @@ export default {
     width: 140px;
   }
 }
-
 </style>

+ 21 - 1
src/views/authentic/auth/index.vue

@@ -31,12 +31,15 @@
         <el-option label="待上线" :value="2" />
         <el-option label="未上线" :value="0" />
       </el-select>
+
       <el-button icon="el-icon-search" type="primary" @click="getList">查询</el-button>
       <!-- <el-button v-if="isProxy" icon="el-icon-edit" type="primary" @click="handleShowEditDialog('添加品牌授权')">添加品牌授权</el-button> -->
       <el-button v-if="isProxy" icon="el-icon-edit" type="primary" @click="$_navigationTo('/auth/auth-add')">添加</el-button>
       <el-button icon="el-icon-upload" type="primary" @click="improtDialogVisible = true">导入</el-button>
       <el-button icon="el-icon-document" type="primary" @click="handleExportExcel">导出</el-button>
       <el-button icon="el-icon-document-copy" type="primary" @click="downLoadExportExcel">获取导入模板</el-button>
+      <el-button type="primary" icon="el-icon-download" @click="handleExport(1)">一键下载授权牌</el-button>
+      <el-button type="primary" icon="el-icon-download" @click="handleExport(2)">一键下载二维码</el-button>
     </div>
     <!-- 表格区域 -->
     <el-table
@@ -107,7 +110,7 @@
       <el-table-column label="操作" align="center" width="400px" class-name="small-padding fixed-width">
         <template slot-scope="{row}">
           <template v-if="isProxy">
-            <el-button type="primary" size="mini" @click="handleShowEditDialog('编辑品牌授权',row)">
+            <el-button type="primary" size="mini" @click="$_navigationTo(`/auth/auth-edit?id=${row.authId}&authParty=${row.authParty}`)">
               编辑
             </el-button>
             <el-button type="primary" size="mini" @click="$_navigationTo(`/auth/user-list?id=${row.authId}&authParty=${row.authParty}`)">
@@ -125,6 +128,7 @@
           <el-button v-if="isProxy" type="danger" size="mini" @click="handleRemoveAuth(row)">
             删除
           </el-button>
+
         </template>
       </el-table-column>
     </el-table>
@@ -289,6 +293,22 @@ export default {
       }
     },
 
+    // 导出下载授权牌 || 二维码
+    async handleExport(type) {
+      const confirmText = type === 1 ? '授权牌' : '二维码'
+
+      const text = await this.$confirm(`确认下载所有${confirmText}?`, '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).catch(() => {
+        this.$message.info('已取消操作')
+      })
+      if (text !== 'confirm') return
+      // 使用a链接下载
+      downLoadWithATag(`${process.env.VUE_APP_BASE_API}/download/shop/image?authUserId=${this.authUserId}&type=${type}`)
+    },
+
     // 下载模板
     downLoadExportExcel() {
       downLoadWithATag(`${process.env.VUE_APP_BASE_API}/download/file?ossName=%E6%AD%A3%E5%93%81%E8%81%94%E7%9B%9F%E6%9C%BA%E6%9E%84%E3%80%81%E5%95%86%E5%93%81%E5%AF%BC%E5%85%A5%E6%A8%A1%E6%9D%BF.xlsx&fileName=%E6%AD%A3%E5%93%81%E8%81%94%E7%9B%9F%E6%9C%BA%E6%9E%84%E3%80%81%E5%95%86%E5%93%81%E5%AF%BC%E5%85%A5%E6%A8%A1%E6%9D%BF.xlsx`)

+ 114 - 8
src/views/authentic/components/authCardTemplate.vue

@@ -1,36 +1,102 @@
 <template>
-  <el-radio-group v-model="radio" size="mini" class="auth-card-template">
+  <el-radio-group v-model="radio" size="mini" class="auth-card-template" @change="handleRadioChange">
     <el-row :gutter="16">
       <el-col :span="8">
-        <img class="cover" src="https://picsum.photos/160/120" alt="">
+        <img class="cover" :src="authCard1" alt="">
         <div class="footer">
           <el-radio :label="1">模板一</el-radio>
-          <el-button type="primary" size="mini" round>预览</el-button>
+          <el-button type="primary" size="mini" round @click="preview(1)">预览</el-button>
         </div>
       </el-col>
       <el-col :span="8">
-        <img class="cover" src="https://picsum.photos/160/120" alt="">
+        <img class="cover" :src="authCard2" alt="">
         <div class="footer">
           <el-radio :label="2">模板二</el-radio>
-          <el-button type="primary" size="mini" round>预览</el-button>
+          <el-button type="primary" size="mini" round @click="preview(2)">预览</el-button>
         </div>
       </el-col>
       <el-col :span="8">
-        <img class="cover" src="https://picsum.photos/160/120" alt="">
+        <img class="cover" :src="authCard3" alt="">
         <div class="footer">
           <el-radio :label="3">模板三</el-radio>
-          <el-button type="primary" size="mini" round>预览</el-button>
+          <el-button type="primary" size="mini" round @click="preview(3)">预览</el-button>
         </div>
       </el-col>
     </el-row>
+
+    <el-dialog :visible.sync="dialogVisible">
+      <div class="preview">
+        <img :src="previewUrl" alt="">
+        <img v-show="showQrcode" class="qrcode" :class="['type' + previewType]" :src="qrcodeUrl">
+      </div>
+    </el-dialog>
   </el-radio-group>
 </template>
 
 <script>
+import QRCode from 'qrcode'
+import authCard1 from '@/assets/img/auth-card-placeholder-01.png'
+import authCard2 from '@/assets/img/auth-card-placeholder-02.png'
+import authCard3 from '@/assets/img/auth-card-placeholder-03.png'
 export default {
+  model: {
+    event: 'change',
+    prop: 'radio'
+  },
+  props: {
+    imageList: {
+      type: Array,
+      default: () => []
+    },
+    showQrcode: {
+      type: Boolean,
+      default: true
+    },
+    radio: {
+      type: Number,
+      default: 1
+    }
+  },
   data() {
     return {
-      radio: 1
+      authCard1,
+      authCard2,
+      authCard3,
+      previewUrl: '',
+      dialogVisible: false,
+      previewType: -1,
+      qrcodeUrl: ''
+    }
+  },
+  computed: {
+    drawImage() {
+      return this.imageList[0].url
+    }
+  },
+  created() {
+    this.drawQrcode()
+  },
+  methods: {
+    handleRadioChange() {
+      this.$emit('change', this.radio)
+    },
+
+    async drawQrcode() {
+      const options = {
+        width: 192,
+        height: 192,
+        margin: 1
+      }
+
+      this.qrcodeUrl = await QRCode.toDataURL('undefined', options)
+
+      console.log(this.qrcodeUrl)
+    },
+
+    preview(type) {
+      this.previewType = type
+      this.dialogVisible = true
+      this.previewUrl = this.drawImage
     }
   }
 }
@@ -53,4 +119,44 @@ export default {
     padding:0 8px;
   }
 }
+
+.preview{
+  max-width: 920px;
+  max-height: 690px;
+  position: relative;
+  overflow: hidden;
+  img{
+    width: 100%;
+    max-height: 100%;
+    display: block;
+    position: relative;
+    z-index: 5;
+  }
+  .qrcode{
+    width: 100px;
+    height: 100px;
+    position: absolute;
+
+    z-index: 9;
+
+    background: red;
+
+    &.type1{
+      bottom: 70px;
+      left: 70px;
+    }
+
+    &.type3{
+      top: 50%;
+      transform: translateY(-50%);
+      left: 70px;
+    }
+
+    &.type2{
+      top: 50%;
+      transform: translateY(-50%);
+      right: 70px;
+    }
+  }
+}
 </style>

+ 73 - 65
src/views/authentic/components/deviceSection.vue

@@ -2,32 +2,22 @@
   <div class="device-section">
     <div v-for="formData in formDataList" :key="formData.key" class="section">
       <i v-if="formDataList.length > 1" class="el-icon-close remove" title="移除该项" @click="removeOne(formData)" />
-      <el-form label-width="90px" :model="formData" :rules="rules">
-        <el-form-item label="设备名称:" prop="deviceName">
-          <el-input v-model="formData.deviceName" placeholder="设备名称" />
+      <el-form :ref="'form' + formData.uuid" label-width="90px" :model="formData" :rules="rules">
+        <el-form-item label="设备名称:" prop="equipmentName">
+          <el-input v-model="formData.equipmentName" placeholder="设备名称" />
         </el-form-item>
-        <el-form-item label="所属品牌:" prop="deviceBrand">
-          <el-input v-model="formData.deviceBrand" placeholder="所属品牌" />
+        <el-form-item label="所属品牌:" prop="brand">
+          <el-input v-model="formData.brand" placeholder="所属品牌" />
         </el-form-item>
-        <el-form-item label="设备图片:" prop="deviceImage">
-          <el-input v-show="false" v-model="formData.deviceImage" placeholder="设备图片" />
-          <el-upload
-            ref="coverUploader"
-            :class="{ 'el-upload-hidden': bannerList.length >= 1}"
-            list-type="picture-card"
-            :action="action"
-            :headers="headers"
-            :on-success="uploadBannerSuccess"
-            :on-remove="handleBannerRemove"
-            :before-upload="beforeBannerUpload"
-            :limit="1"
-            multiple
-            accept=".jpg,.png,.gif"
-            :file-list="bannerList"
-          >
-            <div slot="tip" class="el-upload__tip">建议尺寸:542px * 542px</div>
-            <i slot="default" class="el-icon-plus" />
-          </el-upload>
+        <el-form-item label="设备图片:" prop="image">
+          <el-input v-show="false" v-model="formData.image" placeholder="设备图片" />
+          <upload-image
+            tip="建议尺寸:542px * 542px"
+            :image-list="formData.imageList"
+            :before-upload="beforeImageUpload"
+            @success="uploadImageSuccess($event, formData)"
+            @remove="handleImageRemove($event, formData)"
+          />
         </el-form-item>
       </el-form>
     </div>
@@ -36,9 +26,12 @@
 </template>
 
 <script>
-import { mapGetters } from 'vuex'
+import UploadImage from '@/components/UploadImage'
 export default {
   name: 'DeviceSection',
+  components: {
+    UploadImage
+  },
   props: {
     list: {
       type: Array,
@@ -49,73 +42,88 @@ export default {
     return {
       uuid: 0, // key
       formDataList: [],
-      bannerList: [],
-
-      deviceImageList: [],
       rules: {
-        deviceName: [{ required: true, message: '设备名称不能为空', trigger: ['blur', 'change'] }],
-        deviceBrand: [{ required: true, message: '设备名称不能为空', trigger: ['blur', 'change'] }],
-        deviceImage: [{ required: true, message: '设备名称不能为空', trigger: 'change' }]
-      }
-    }
-  },
-  computed: {
-    ...mapGetters(['token']),
-    // 图片上传
-    action() {
-      return process.env.VUE_APP_UPLOAD_API + '/upload/image'
-    },
-    headers() {
-      return {
-        'X-Token': this.token
+        equipmentName: [{ required: true, message: '设备名称不能为空', trigger: ['blur', 'change'] }],
+        brand: [{ required: true, message: '所属品牌不能为空', trigger: ['blur', 'change'] }],
+        image: [{ required: true, message: '请上传设备图片', trigger: 'change' }]
       }
     }
   },
   created() {
-    this.$watch(() => this.formDataList, (newVal) => {
-      this.$emit('change', newVal)
-    })
     this.init()
   },
   methods: {
-    formListWatchHnadle(nVal) {
-      console.log(nVal)
-      console.log(this)
-    },
     init() {
+      // 监听表单数据列表边变化
+      this.$watch(
+        () => this.formDataList,
+        newVal => {
+          this.$emit('change', newVal)
+        }, { deep: true }
+      )
+      // 初始化表单列表
+      this.initFormData()
+    },
+    // 表单验证
+    valideAllForm() {
+      const validateList = []
+      for (const key in this.$refs) {
+        if (key.indexOf('form') > -1 && Object.hasOwnProperty.call(this.$refs, key)) {
+          const form = this.$refs[key][0]
+          if (form) {
+            validateList.push(form.validate())
+          }
+        }
+      }
+      return Promise.all(validateList)
+    },
+    // 初始化表单
+    initFormData() {
       if (this.list.length <= 0) {
         this.insertOne()
       } else {
         this.formDataList = this.makeUuid(this.list)
       }
     },
+    // 出入一条表单数据
     insertOne() {
       this.uuid++
       this.formDataList.push({
         uuid: this.uuid,
-        deviceName: '',
-        deviceBrand: '',
-        deviceImage: ''
+        equipmentName: '',
+        brand: '',
+        image: '',
+        imageList: []
       })
     },
+    // 删除一条表单数据
     removeOne(formData) {
       const findIndex = this.formDataList.findIndex(item => item.uuid === formData.uuid)
       this.formDataList.splice(findIndex, 1)
-      console.log(findIndex)
+      console.log(this.formDataList)
     },
     // 初始化列表uuid
     makeUuid(list = []) {
-      return list.map((item, index) => ({ uuid: index, ...item }))
+      return list.map((item, index) => {
+        const obj = { uuid: index, imageList: [], ...item }
+        if (item.image) {
+          obj.imageList.push({ name: '', url: item.image })
+        }
+        return obj
+      })
     },
-    // banner上传
-    uploadBannerSuccess(response, file, fileList) {
-      this.bannerList = fileList
-      console.log(this.bannerList)
+    // 设备图片上传
+    uploadImageSuccess({ response, file, fileList }, current) {
+      current.image = response.data
+      current.imageList.splice(0, current.imageList.length, ...fileList)
     },
-    handleBannerRemove(file, fileList) {
-      this.bannerList = fileList
+    // 设备图片移除
+    handleImageRemove({ file, fileList }, current) {
+      current.image = ''
+      current.imageList.splice(0, current.imageList.length, ...fileList)
     },
-    beforeBannerUpload(file) {
+    // 上传图片限制
+    beforeImageUpload(file) {
       const flag = file.size / 1024 / 1024 < 1
       if (!flag) {
         this.$message.error('上传banner图片大小不能超过 1MB!')
@@ -139,12 +147,12 @@ export default {
       top: 6px;
       font-size: 14px;
       cursor: pointer;
-      background: #F56C6C;
+      background: #f56c6c;
       color: #fff;
       padding: 2px;
       border-radius: 50%;
-      transition:all 0.2s;
-      &:hover{
+      transition: all 0.2s;
+      &:hover {
         background: red;
       }
     }

+ 94 - 97
src/views/authentic/doctor/add.vue

@@ -1,38 +1,40 @@
 <template>
   <div class="doctor-edit">
-    <el-form class="doctor-edit-form" label-width="130px" :model="formData" :rules="rules">
-      <el-form-item label="医师姓名:" prop="name">
-        <el-input v-model="formData.name" placeholder="请输入医师姓名" />
+    <el-form ref="submitForm" class="doctor-edit-form" label-width="140px" :model="formData" :rules="rules">
+      <el-form-item label="医师姓名:" prop="doctorName">
+        <el-input v-model="formData.doctorName" placeholder="请输入医师姓名" />
       </el-form-item>
-      <el-form-item label="从业资格证编号:" prop="name">
-        <el-input v-model="formData.name" placeholder="请输入从业资格证编号" />
+      <el-form-item label="从业资格证编号:" prop="certificateNo">
+        <el-input v-model="formData.certificateNo" placeholder="请输入从业资格证编号" />
       </el-form-item>
-      <el-form-item label="所在机构:" prop="name">
-        <el-input v-model="formData.name" placeholder="请输入机构名称" />
+      <el-form-item label="所在机构:" prop="clubName">
+        <el-input v-model="formData.clubName" placeholder="请输入机构名称" />
+      </el-form-item>
+      <el-form-item label="医师照片:" prop="doctorImage">
+        <el-input v-show="false" v-model="formData.doctorImage" />
+        <upload-image
+          tip="建议尺寸:200px * 200px"
+          :image-list="doctorImageList"
+          :before-upload="beforeDoctorImageUpload"
+          @success="uploadDoctorImageSuccess"
+          @remove="handleDoctorImageRemove"
+        />
       </el-form-item>
       <el-form-item label="轮播图:" prop="banner">
         <el-input v-show="false" v-model="formData.banner" />
-        <el-upload
-          ref="coverUploader"
-          :class="{ 'el-upload-hidden': bannerList.length >= 2}"
-          list-type="picture-card"
-          :action="action"
-          :headers="headers"
-          :on-success="uploadBannerSuccess"
-          :on-remove="handleBannerRemove"
+        <upload-image
+          tip="至少上传一张机构门店图,最多上传6张;建议尺寸:542px * 542px"
+          :image-list="bannerList"
+          :limit="6"
           :before-upload="beforeBannerUpload"
-          :limit="2"
-          multiple
-          accept=".jpg,.png,.gif"
-          :file-list="bannerList"
-        >
-          <div slot="tip" class="el-upload__tip">至少上传一张机构门店图,最多上传6张;建议尺寸:542px * 542px</div>
-          <i slot="default" class="el-icon-plus" />
-        </el-upload>
+          @success="uploadBannerSuccess"
+          @remove="handleBannerRemove"
+        />
       </el-form-item>
 
-      <el-form-item label="具备操作资格设备:">
-        <device-section :list="deviceList" @change="deviceListDataChange" />
+      <el-form-item label="具备操作资格设备:" prop="equipment">
+        <el-input v-show="false" v-model="formData.equipment" />
+        <device-section ref="subForm" :list="deviceList" @change="deviceListDataChange" />
       </el-form-item>
 
     </el-form>
@@ -44,68 +46,36 @@
 </template>
 
 <script>
+import { Promise } from 'jszip/lib/external'
 import { mapGetters } from 'vuex'
 import DeviceSection from '../components/deviceSection.vue'
+import UploadImage from '@/components/UploadImage'
+import { doctorSave } from '@/api/doctor'
+
 export default {
-  components: { DeviceSection },
+  components: { DeviceSection, UploadImage },
   data() {
     return {
-      dialogMapVisible: false,
       point: {},
-      value: [],
-      options: [{
-        value: 'zhinan',
-        label: '指南',
-        children: [{
-          value: 'shejiyuanze',
-          label: '设计原则',
-          children: [{
-            value: 'yizhi',
-            label: '一致'
-          }, {
-            value: 'fankui',
-            label: '反馈'
-          }, {
-            value: 'xiaolv',
-            label: '效率'
-          }, {
-            value: 'kekong',
-            label: '可控'
-          }]
-        }, {
-          value: 'daohang',
-          label: '导航',
-          children: [{
-            value: 'cexiangdaohang',
-            label: '侧向导航'
-          }, {
-            value: 'dingbudaohang',
-            label: '顶部导航'
-          }]
-        }]
-      }],
       disabled: false,
       formData: {
-        name: '',
-        address: '',
-        fullAddress: '',
-        point: '',
-        mobile: '',
-        logoImage: '',
-        banner: ''
+        doctorName: '',
+        certificateNo: '',
+        clubName: '',
+        banner: '',
+        doctorImage: '',
+        equipment: ''
       },
       rules: {
-        name: [{ required: true, message: '机构名称不能为空', trigger: ['blur', 'change'] }],
-        address: [{ required: true, message: '地址不能为空', trigger: 'change' }],
-        fullAddress: [{ required: true, message: '详细不能为空', trigger: ['blur', 'change'] }],
-        point: [{ required: true, message: '地址坐标不能为空', trigger: ['blur', 'change'] }],
-        mobile: [{ required: true, message: '联系方式不能为空', trigger: ['blur', 'change'] }],
-        logoImage: [{ required: true, message: '请上传机构logo', trigger: 'change' }],
-        banner: [{ required: true, message: '请至少上传一张banner图片', trigger: 'change' }]
-
+        doctorName: [{ required: true, message: '医师姓名不能为空', trigger: ['blur', 'change'] }],
+        certificateNo: [{ required: true, message: '从业资格证编号不能为空', trigger: ['blur', 'change'] }],
+        clubName: [{ required: true, message: '所在机构不能为空', trigger: ['blur', 'change'] }],
+        doctorImage: [{ required: true, message: '请上传医师照片', trigger: 'change' }],
+        banner: [{ required: true, message: '请上传至少一张轮播图', trigger: 'change' }],
+        equipment: [{ required: true, message: '具备操作资格设备不能为空', trigger: 'change' }]
       },
       // logo图片列表
-      logoList: [],
+      doctorImageList: [],
       // banner图片列表
       bannerList: [],
       // 资格仪器列表
@@ -113,7 +83,7 @@ export default {
     }
   },
   computed: {
-    ...mapGetters(['token']),
+    ...mapGetters(['token', 'authUserId', 'proxyInfo']),
     // 图片上传
     action() {
       return process.env.VUE_APP_UPLOAD_API + '/upload/image'
@@ -130,40 +100,67 @@ export default {
   methods: {
     // 具备操作资格设备列表数据变化
     deviceListDataChange(list) {
-      console.log(list)
+      this.deviceList = list
+      this.formData.equipment = list.length || ''
     },
-    handlePointChange(point) {
-      console.log(point)
-      this.formData.point = `${point.lat},${point.lng}`
+
+    // 提交表单验证
+    submit() {
+      Promise.all([this.$refs.subForm.valideAllForm(), this.$refs.submitForm.validate()]).then(res => {
+        this.save()
+      })
     },
-    submit() {},
-    handleChange(e) {
-      console.log(e)
+
+    // 保存
+    save() {
+      const authUserId = this.proxyInfo?.authUserId || this.authUserId
+
+      const data = {
+        authUserId,
+        createBy: authUserId,
+        doctorId: '',
+        doctorName: this.formData.doctorName,
+        certificateNo: this.formData.certificateNo,
+        clubName: this.formData.clubName,
+        doctorImage: this.formData.doctorImage
+      }
+
+      console.log(this.formData)
+
+      data.bannerList = this.bannerList.map(item => item.response ? item.response.data : item.url)
+      data.equipmentList = this.deviceList.map(item => ({ equipmentName: item.equipmentName, brand: item.brand, image: item.image }))
+      doctorSave(data).then(res => {
+        this.$message.success('保存成功')
+        this.$store.dispatch('tagsView/delView', this.$route)
+        this.$router.push('/doctor/list')
+      })
     },
-    // logo上传
-    uploadLogoSuccess(response, file, fileList) {
-      this.logoList = fileList
-      this.formData.logoImage = fileList[0].response.data
+
+    // 医师照片上传
+    uploadDoctorImageSuccess({ response, file, fileList }) {
+      this.doctorImageList = fileList
+      this.formData.doctorImage = response.data
     },
-    handleLogoRemove(file, fileList) {
-      this.logoList = fileList
-      this.formData.logoImage = ''
+    handleDoctorImageRemove({ file, fileList }) {
+      this.doctorImageList = fileList
+      this.formData.doctorImage = ''
     },
-    beforeLogoUpload(file) {
-      const flag = file.size / 1024 < 500
+    beforeDoctorImageUpload(file) {
+      const flag = file.size / 1024 / 1024 < 1
       if (!flag) {
-        this.$message.error('上传logo图片大小不能超过 500kb!')
+        this.$message.error('上传医师照片大小不能超过 1MB!')
       }
       return flag
     },
 
     // banner上传
-    uploadBannerSuccess(response, file, fileList) {
+    uploadBannerSuccess({ response, file, fileList }) {
       this.bannerList = fileList
-      console.log(this.bannerList)
+      this.formData.banner = fileList.length || ''
     },
-    handleBannerRemove(file, fileList) {
+    handleBannerRemove({ file, fileList }) {
       this.bannerList = fileList
+      this.formData.banner = fileList.length || ''
     },
     beforeBannerUpload(file) {
       const flag = file.size / 1024 / 1024 < 1
@@ -182,7 +179,7 @@ export default {
 }
 
 .doctor-edit-form {
-  width: 600px;
+  width: 650px;
   margin: 0 auto;
   margin-top: 80px;
 }

+ 123 - 99
src/views/authentic/doctor/edit.vue

@@ -1,38 +1,40 @@
 <template>
   <div class="doctor-edit">
-    <el-form class="doctor-edit-form" label-width="130px" :model="formData" :rules="rules">
-      <el-form-item label="医师姓名:" prop="name">
-        <el-input v-model="formData.name" placeholder="请输入医师姓名" />
+    <el-form ref="submitForm" class="doctor-edit-form" label-width="140px" :model="formData" :rules="rules">
+      <el-form-item label="医师姓名:" prop="doctorName">
+        <el-input v-model="formData.doctorName" placeholder="请输入医师姓名" />
       </el-form-item>
-      <el-form-item label="从业资格证编号:" prop="name">
-        <el-input v-model="formData.name" placeholder="请输入从业资格证编号" />
+      <el-form-item label="从业资格证编号:" prop="certificateNo">
+        <el-input v-model="formData.certificateNo" placeholder="请输入从业资格证编号" />
       </el-form-item>
-      <el-form-item label="所在机构:" prop="name">
-        <el-input v-model="formData.name" placeholder="请输入机构名称" />
+      <el-form-item label="所在机构:" prop="clubName">
+        <el-input v-model="formData.clubName" placeholder="请输入机构名称" />
+      </el-form-item>
+      <el-form-item label="医师照片:" prop="doctorImage">
+        <el-input v-show="false" v-model="formData.doctorImage" />
+        <upload-image
+          tip="建议尺寸:200px * 200px"
+          :image-list="doctorImageList"
+          :before-upload="beforeDoctorImageUpload"
+          @success="uploadDoctorImageSuccess"
+          @remove="handleDoctorImageRemove"
+        />
       </el-form-item>
       <el-form-item label="轮播图:" prop="banner">
         <el-input v-show="false" v-model="formData.banner" />
-        <el-upload
-          ref="coverUploader"
-          :class="{ 'el-upload-hidden': bannerList.length >= 2}"
-          list-type="picture-card"
-          :action="action"
-          :headers="headers"
-          :on-success="uploadBannerSuccess"
-          :on-remove="handleBannerRemove"
+        <upload-image
+          tip="至少上传一张机构门店图,最多上传6张;建议尺寸:542px * 542px"
+          :image-list="bannerList"
+          :limit="6"
           :before-upload="beforeBannerUpload"
-          :limit="2"
-          multiple
-          accept=".jpg,.png,.gif"
-          :file-list="bannerList"
-        >
-          <div slot="tip" class="el-upload__tip">至少上传一张机构门店图,最多上传6张;建议尺寸:542px * 542px</div>
-          <i slot="default" class="el-icon-plus" />
-        </el-upload>
+          @success="uploadBannerSuccess"
+          @remove="handleBannerRemove"
+        />
       </el-form-item>
 
-      <el-form-item label="具备操作资格设备:">
-        <device-section @change="deviceListDataChange" />
+      <el-form-item label="具备操作资格设备:" prop="equipment">
+        <el-input v-show="false" v-model="formData.equipment" />
+        <device-section v-if="!isRequest" ref="subForm" :list="deviceList" @change="deviceListDataChange" />
       </el-form-item>
 
     </el-form>
@@ -44,74 +46,46 @@
 </template>
 
 <script>
+import { Promise } from 'jszip/lib/external'
 import { mapGetters } from 'vuex'
 import DeviceSection from '../components/deviceSection.vue'
+import UploadImage from '@/components/UploadImage'
+import { doctorSave, doctorFormData } from '@/api/doctor'
+
 export default {
-  components: { DeviceSection },
+  components: { DeviceSection, UploadImage },
   data() {
     return {
-      dialogMapVisible: false,
+      isRequest: true,
+      doctorId: '',
       point: {},
-      value: [],
-      options: [{
-        value: 'zhinan',
-        label: '指南',
-        children: [{
-          value: 'shejiyuanze',
-          label: '设计原则',
-          children: [{
-            value: 'yizhi',
-            label: '一致'
-          }, {
-            value: 'fankui',
-            label: '反馈'
-          }, {
-            value: 'xiaolv',
-            label: '效率'
-          }, {
-            value: 'kekong',
-            label: '可控'
-          }]
-        }, {
-          value: 'daohang',
-          label: '导航',
-          children: [{
-            value: 'cexiangdaohang',
-            label: '侧向导航'
-          }, {
-            value: 'dingbudaohang',
-            label: '顶部导航'
-          }]
-        }]
-      }],
       disabled: false,
       formData: {
-        name: '',
-        address: '',
-        fullAddress: '',
-        point: '',
-        mobile: '',
-        logoImage: '',
-        banner: ''
+        doctorName: '',
+        certificateNo: '',
+        clubName: '',
+        banner: '',
+        doctorImage: '',
+        equipment: ''
       },
       rules: {
-        name: [{ required: true, message: '机构名称不能为空', trigger: ['blur', 'change'] }],
-        address: [{ required: true, message: '地址不能为空', trigger: 'change' }],
-        fullAddress: [{ required: true, message: '详细不能为空', trigger: ['blur', 'change'] }],
-        point: [{ required: true, message: '地址坐标不能为空', trigger: ['blur', 'change'] }],
-        mobile: [{ required: true, message: '联系方式不能为空', trigger: ['blur', 'change'] }],
-        logoImage: [{ required: true, message: '请上传机构logo', trigger: 'change' }],
-        banner: [{ required: true, message: '请至少上传一张banner图片', trigger: 'change' }]
-
+        doctorName: [{ required: true, message: '医师姓名不能为空', trigger: ['blur', 'change'] }],
+        certificateNo: [{ required: true, message: '从业资格证编号不能为空', trigger: ['blur', 'change'] }],
+        clubName: [{ required: true, message: '所在机构不能为空', trigger: ['blur', 'change'] }],
+        doctorImage: [{ required: true, message: '请上传医师照片', trigger: 'change' }],
+        banner: [{ required: true, message: '请上传至少一张轮播图', trigger: 'change' }],
+        equipment: [{ required: true, message: '具备操作资格设备不能为空', trigger: 'change' }]
       },
       // logo图片列表
-      logoList: [],
+      doctorImageList: [],
       // banner图片列表
-      bannerList: []
+      bannerList: [],
+      // 资格仪器列表
+      deviceList: []
     }
   },
   computed: {
-    ...mapGetters(['token']),
+    ...mapGetters(['token', 'authUserId', 'proxyInfo']),
     // 图片上传
     action() {
       return process.env.VUE_APP_UPLOAD_API + '/upload/image'
@@ -123,45 +97,95 @@ export default {
     }
   },
   created() {
-
+    this.doctorId = parseInt(this.$route.query.id)
+    this.initFormData()
   },
   methods: {
     // 具备操作资格设备列表数据变化
     deviceListDataChange(list) {
-      console.log(list)
+      this.deviceList = list
+      this.formData.equipment = list.length || ''
     },
-    handlePointChange(point) {
-      console.log(point)
-      this.formData.point = `${point.lat},${point.lng}`
+
+    // 表单数据回显
+    initFormData() {
+      doctorFormData({ doctorId: this.doctorId }).then(res => {
+        this.setFormData(res.data)
+      })
     },
-    submit() {},
-    handleChange(e) {
-      console.log(e)
+
+    // 设置表单数据
+    setFormData(data) {
+      this.formData.doctorName = data.doctorName
+      this.formData.certificateNo = data.certificateNo
+      this.formData.clubName = data.clubName
+      this.formData.doctorImage = data.doctorImage
+
+      this.formData.banner = data.bannerList.length
+      this.formData.equipmentList = data.equipmentList.length
+      this.doctorImageList.push({ url: data.doctorImage, name: 'doctor' })
+      this.bannerList = data.bannerList.map(item => ({ url: item, name: '' }))
+      this.deviceList = data.equipmentList
+
+      this.isRequest = false
     },
-    // logo上传
-    uploadLogoSuccess(response, file, fileList) {
-      this.logoList = fileList
-      this.formData.logoImage = fileList[0].response.data
+
+    // 提交表单验证
+    submit() {
+      Promise.all([this.$refs.subForm.valideAllForm(), this.$refs.submitForm.validate()]).then(res => {
+        this.save()
+      })
     },
-    handleLogoRemove(file, fileList) {
-      this.logoList = fileList
-      this.formData.logoImage = ''
+
+    // 保存
+    save() {
+      const authUserId = this.proxyInfo?.authUserId || this.authUserId
+      const data = {
+        authUserId,
+        createBy: authUserId,
+        doctorId: this.doctorId,
+        doctorName: this.formData.doctorName,
+        certificateNo: this.formData.certificateNo,
+        clubName: this.formData.clubName,
+        doctorImage: this.formData.doctorImage
+      }
+
+      console.log(this.formData)
+
+      data.bannerList = this.bannerList.map(item => item.response ? item.response.data : item.url)
+      data.equipmentList = this.deviceList.map(item => ({ equipmentName: item.equipmentName, brand: item.brand, image: item.image }))
+      doctorSave(data).then(res => {
+        this.$message.success('保存成功')
+        this.$store.dispatch('tagsView/delView', this.$route)
+        this.$router.push('/doctor/list')
+      })
     },
-    beforeLogoUpload(file) {
-      const flag = file.size / 1024 < 500
+
+    // 医师照片上传
+    uploadDoctorImageSuccess({ response, file, fileList }) {
+      this.doctorImageList = fileList
+      this.formData.doctorImage = response.data
+    },
+    handleDoctorImageRemove({ file, fileList }) {
+      this.doctorImageList = fileList
+      this.formData.doctorImage = ''
+    },
+    beforeDoctorImageUpload(file) {
+      const flag = file.size / 1024 / 1024 < 1
       if (!flag) {
-        this.$message.error('上传logo图片大小不能超过 500kb!')
+        this.$message.error('上传医师照片大小不能超过 1MB!')
       }
       return flag
     },
 
     // banner上传
-    uploadBannerSuccess(response, file, fileList) {
+    uploadBannerSuccess({ response, file, fileList }) {
       this.bannerList = fileList
-      console.log(this.bannerList)
+      this.formData.banner = fileList.length || ''
     },
-    handleBannerRemove(file, fileList) {
+    handleBannerRemove({ file, fileList }) {
       this.bannerList = fileList
+      this.formData.banner = fileList.length || ''
     },
     beforeBannerUpload(file) {
       const flag = file.size / 1024 / 1024 < 1
@@ -180,7 +204,7 @@ export default {
 }
 
 .doctor-edit-form {
-  width: 600px;
+  width: 650px;
   margin: 0 auto;
   margin-top: 80px;
 }

+ 65 - 18
src/views/authentic/doctor/index.vue

@@ -2,7 +2,7 @@
   <div class="app-container">
     <div class="filter-container">
       <span>医师姓名:</span>
-      <el-input v-model="listQuery.productName" placeholder="医师姓名" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
+      <el-input v-model="listQuery.doctorName" placeholder="医师姓名" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
       <span>审核状态:</span>
       <el-select
         v-model="listQuery.auditStatus"
@@ -46,8 +46,8 @@
       header-row-class-name="tableHeader"
     >
       <el-table-column label="序号" :index="indexMethod" type="index" align="center" width="80" />
-      <el-table-column label="医生姓名" align="center" prop="productName" />
-      <el-table-column label="从业资格证编号" align="center" prop="snCode" />
+      <el-table-column label="医生姓名" align="center" prop="doctorName" />
+      <el-table-column label="从业资格证编号" align="center" prop="certificateNo" />
 
       <el-table-column label="审核状态" width="220px" align="center">
         <template slot-scope="{ row }">
@@ -101,14 +101,12 @@
       <!-- <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}">
-          <template v-if="userIdentity === 2|| proxyInfo !== null">
-            <el-button type="default" size="mini" @click="$_navigationTo(`edit?id=${row.productId}`)">
-              编辑
-            </el-button>
-            <el-button type="danger" size="mini" @click="handleRemoveDoctor(row)">
-              删除
-            </el-button>
-          </template>
+          <el-button type="primary" size="mini" @click="$_navigationTo(`edit?id=${row.doctorId}`)">
+            编辑
+          </el-button>
+          <el-button type="danger" size="mini" @click="handleRemoveDoctor(row)">
+            删除
+          </el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -119,29 +117,78 @@
 
 <script>
 import Pagination from '@/components/Pagination' // secondary package based on el-pagination
+import { mapGetters } from 'vuex'
+import { formatDate } from '@/utils'
+import { fetchDoctorList, removeDoctor, doctorStatusChange } from '@/api/doctor'
+
 export default {
   components: { Pagination },
+  filters: {
+    formatTime(time) {
+      if (!time) {
+        return ''
+      }
+      return formatDate(time, 'yyyy-MM-DD HH:mm:ss')
+    }
+  },
   data() {
     return {
       listLoading: false,
       tableKey: 0,
       total: 0,
       listQuery: {
-        status: '',
+        listType: 1,
+        doctorName: '',
         auditStatus: '',
-        authId: '',
-        productName: '',
-        snCode: '',
+        status: '',
         pageNum: 1,
         pageSize: 10
       },
       list: []
     }
   },
+  computed: {
+    ...mapGetters(['authUserId', 'proxyInfo'])
+  },
+  created() {
+    this.getList()
+  },
   methods: {
-    getList() {},
-    handleChangeStatus() {},
-    handleRemoveDoctor() {},
+    // 获取列表
+    getList() {
+      this.listQuery.authUserId = this.proxyInfo?.authUserId || this.authUserId
+      fetchDoctorList(this.listQuery).then(res => {
+        console.log(res)
+        this.list = res.data.list
+        this.total = res.data.total
+      })
+    },
+    // 修改状态
+    handleChangeStatus(row) {
+      const status = row.status === 1 ? 0 : 1
+
+      doctorStatusChange({ doctorId: row.doctorId, status }).then(res => {
+        this.$message.success('状态修改成功')
+        this.getList()
+      })
+    },
+    // 删除
+    async handleRemoveDoctor(row) {
+      const text = await this.$confirm('确认删除该医师信息吗?删除后不可恢复', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).catch(() => {
+        this.$message.info('已取消操作')
+      })
+      if (text !== 'confirm') return
+
+      removeDoctor({ doctorId: row.doctorId }).then(res => {
+        this.$message.success('删除成功')
+        this.getList()
+      })
+    },
+    // 表格索引
     indexMethod(index) {
       return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1
     }

+ 76 - 16
src/views/authentic/product/add.vue

@@ -22,23 +22,35 @@
       </el-form-item>
 
       <el-form-item label="设备图片:" prop="productImage">
-        <upload-image ref="uploadImageRef2" tip-title="542px*542px" @success="imageUploadSuccess1" />
+        <upload-image
+          tip="建议尺寸:542px * 542px"
+          :image-list="productImageList"
+          :before-upload="beforeProductImageUpload"
+          @success="uploadProductImageSuccess"
+          @remove="handleProductImageRemove"
+        />
         <el-input v-model="formData.productImage" class="hiddenInput" />
       </el-form-item>
       <el-form-item label="授权牌:" prop="certificateImage">
-        <upload-image ref="uploadImageRef2" tip-title="150px*112px" @success="imageUploadSuccess2" />
+        <upload-image
+          tip="建议尺寸:150px * 112px"
+          :image-list="certificateImageList"
+          :before-upload="beforeCertificateImageUpload"
+          @success="uploadCertificateImageSuccess"
+          @remove="handleCertificateImageRemove"
+        />
         <el-input v-model="formData.certificateImage" class="hiddenInput" />
       </el-form-item>
       <!-- 是否生成二维码授权牌 -->
       <el-form-item label="生成二维码授权牌:">
-        <el-radio-group v-model="radio" size="mini">
+        <el-radio-group v-model="formData.addQrCodeFlag" size="mini" @change="handleRadioChange">
           <el-radio :label="0" border>否</el-radio>
-          <el-radio :label="1" border>是</el-radio>
+          <el-radio :label="1" border :disabled="certificateImageList.length <= 0">是</el-radio>
         </el-radio-group>
       </el-form-item>
       <!-- 二维码授权牌模板 -->
-      <el-form-item v-if="radio===1" label="选择模板:">
-        <auth-card-template />
+      <el-form-item v-if="formData.addQrCodeFlag===1" label="选择模板:">
+        <auth-card-template v-model="formData.addTemplateType" :image-list="certificateImageList" />
       </el-form-item>
 
       <el-form-item label="相关参数:" prop="paramList">
@@ -68,7 +80,7 @@
 </template>
 
 <script>
-import UploadImage from '../components/uploadImage'
+import UploadImage from '@/components/UploadImage'
 import { saveProduct } from '@/api/product'
 import { fetchBrandList } from '@/api/brand'
 import { mapGetters } from 'vuex'
@@ -90,7 +102,6 @@ export default {
       callback()
     }
     return {
-      radio: 0,
       isLoading: false,
       paramsCount: 4,
       brandList: [],
@@ -106,7 +117,9 @@ export default {
         productName: '', //	设备名称
         snCode: '', //	设备SN码
         status: 2, //	上架状态:0下线,1上线 2待审核
-        brandId: ''
+        brandId: '',
+        addQrCodeFlag: 0,
+        addTemplateType: 1
       },
       paramList: [], // 参数列表
       rules: {
@@ -121,7 +134,12 @@ export default {
         brandId: [{ required: true, validator: valideBrandId, tigger: 'change' }]
       },
       // 参数框的提示语
-      tipList: ['例如:品牌', '例如:尺寸', '例如:功率', '例如:重量']
+      tipList: ['例如:品牌', '例如:尺寸', '例如:功率', '例如:重量'],
+
+      // 商品图片列表
+      productImageList: [],
+      // 授权牌照图片列表
+      certificateImageList: []
     }
   },
   computed: {
@@ -149,9 +167,24 @@ export default {
     }
   },
   methods: {
+
+    authCardChange(current) {
+      console.log(current)
+      this.formData.addTemplateType = current
+    },
+
     handleChange() {
       console.log(this.formData)
     },
+
+    handleRadioChange(index) {
+      if (index === 1 && this.certificateImageList.length <= 0) {
+        this.$message.warning('请先上传授权牌')
+        this.formData.addQrCodeFlag = 0
+        return
+      }
+    },
+
     // 提交
     submit() {
       this.formData.paramList = this.setParamToFormData()
@@ -227,14 +260,41 @@ export default {
       this.paramsCount -= 1
       this.paramList.splice(index, 1)
     },
-    // 图片上传成功 产品图片
-    imageUploadSuccess1(data) {
-      this.formData.productImage = data.data
+
+    // 产品图片上传
+    beforeProductImageUpload(file) {
+      const flag = file.size / 1024 / 1024 < 1
+      if (!flag) {
+        this.$message.error('上传产品图片大小不能超过 1MB!')
+      }
+      return flag
+    },
+    uploadProductImageSuccess({ response, file, fileList }) {
+      this.productImageList = fileList
+      this.formData.productImage = response.data
+    },
+    handleProductImageRemove({ file, fileList }) {
+      this.productImageList = fileList
+      this.formData.productImage = ''
     },
-    // 图片上传成功 授权牌照
-    imageUploadSuccess2(data) {
-      this.formData.certificateImage = data.data
+    // 授权牌照上传
+    beforeCertificateImageUpload(file) {
+      const flag = file.size / 1024 / 1024 < 1
+      if (!flag) {
+        this.$message.error('上传授权牌图片大小不能超过 1MB!')
+      }
+      return flag
+    },
+    uploadCertificateImageSuccess({ response, file, fileList }) {
+      this.certificateImageList = fileList
+      this.formData.certificateImage = response.data
     },
+    handleCertificateImageRemove({ file, fileList }) {
+      this.certificateImageList = fileList
+      this.formData.certificateImage = ''
+      this.formData.addQrCodeFlag = 0
+    },
+
     clearFormData() {
       this.paramList = []
       this.paramsCount = 4

+ 108 - 18
src/views/authentic/product/edit.vue

@@ -1,6 +1,6 @@
 <template>
   <div v-loading="isLoading" class="addProduct">
-    <el-form ref="addFormRef" label-width="120px" class="addForm" :model="formData" :rules="rules">
+    <el-form ref="addFormRef" label-width="130px" class="addForm" :model="formData" :rules="rules">
       <el-form-item label="设备名称:" prop="productName">
         <el-input v-model="formData.productName" placeholder="请输入设备名称" />
       </el-form-item>
@@ -16,13 +16,38 @@
       </el-form-item>
 
       <el-form-item label="设备图片:" prop="productImage">
-        <upload-image ref="uploadImageRef2" :file-list="fileList1" @success="imageUploadSuccess1" />
+        <upload-image
+          tip="建议尺寸:542px * 542px"
+          :image-list="productImageList"
+          :before-upload="beforeProductImageUpload"
+          @success="uploadProductImageSuccess"
+          @remove="handleProductImageRemove"
+        />
         <el-input v-model="formData.productImage" class="hiddenInput" />
       </el-form-item>
       <el-form-item label="授权牌:" prop="certificateImage">
-        <upload-image ref="uploadImageRef2" :file-list="fileList2" @success="imageUploadSuccess2" />
+        <upload-image
+          tip="建议尺寸:150px * 112px"
+          :image-list="certificateImageList"
+          :before-upload="beforeCertificateImageUpload"
+          @success="uploadCertificateImageSuccess"
+          @remove="handleCertificateImageRemove"
+        />
         <el-input v-model="formData.certificateImage" class="hiddenInput" />
       </el-form-item>
+
+      <!-- 是否生成二维码授权牌 -->
+      <el-form-item label="生成二维码授权牌:">
+        <el-radio-group v-model="formData.addQrCodeFlag" size="mini" @change="handleRadioChange">
+          <el-radio :label="0" border>否</el-radio>
+          <el-radio :label="1" border :disabled="certificateImageList.length <= 0">是</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <!-- 二维码授权牌模板 -->
+      <el-form-item v-if="formData.addQrCodeFlag===1" label="选择模板:">
+        <auth-card-template v-model="formData.addTemplateType" :image-list="certificateImageList" :show-qrcode="false" />
+      </el-form-item>
+
       <el-form-item label="相关参数:" prop="paramList">
         <div v-for="(item, index) in paramList" :key="index" class="form-group paramsItem">
           <el-input v-model="item.paramName" class="param-title" placeholder="参数名称" maxlength="10" />
@@ -50,13 +75,30 @@
 </template>
 
 <script>
-import UploadImage from '../components/uploadImage'
+import UploadImage from '@/components/UploadImage'
 import { saveProduct, getProductById } from '@/api/product'
 import { fetchBrandList } from '@/api/brand'
 import { mapGetters } from 'vuex'
+import { isSnCode } from '@/utils/validate'
+import AuthCardTemplate from '../components/authCardTemplate.vue'
+
 export default {
-  components: { UploadImage },
+  components: { UploadImage, AuthCardTemplate },
   data() {
+    const valideBrandId = (rules, value, callback) => {
+      if (!value) {
+        return callback(new Error('所属品牌不能为空'))
+      }
+      callback()
+    }
+
+    const valideSNcode = (rules, value, callback) => {
+      if (!isSnCode(value)) {
+        return callback(new Error('只能是字母+数字组合'))
+      }
+      callback()
+    }
+
     return {
       isLoading: false,
       paramsCount: 4,
@@ -71,7 +113,9 @@ export default {
         productImage: '', //	设备图片
         productName: '', //	设备名称
         snCode: '', //	设备SN码
-        brandId: ''
+        brandId: '',
+        addQrCodeFlag: 0,
+        addTemplateType: 1
       },
       paramList: [],
       brandList: [],
@@ -79,14 +123,19 @@ export default {
         certificateImage: [{ required: true, message: '授权牌照不能为空' }],
         paramList: [{ required: true, message: '参数不能为空' }],
         productImage: [{ required: true, message: '设备图片不能为空' }],
-        snCode: [{ required: true, message: 'SN码不能为空' }],
+        snCode: [{ required: true, message: 'SN码不能为空' }, { validator: valideSNcode }],
         productName: [
           { required: true, message: '设备名称不能为空' },
           { max: 50, message: '字数在50字符以内' }
-        ]
+        ],
+        brandId: [{ required: true, validator: valideBrandId, tigger: 'change' }]
       },
       fileList1: [],
-      fileList2: []
+      fileList2: [],
+      // 商品图片列表
+      productImageList: [],
+      // 授权牌照图片列表
+      certificateImageList: []
     }
   },
   computed: {
@@ -158,10 +207,10 @@ export default {
         const productImage = this.formData.productImage
         const certificateImage = this.formData.certificateImage
         if (productImage) {
-          this.fileList1.push({ name: 'productImage', url: productImage })
+          this.productImageList.push({ name: 'productImage', url: productImage })
         }
         if (certificateImage) {
-          this.fileList2.push({ name: 'certificateImage', url: certificateImage })
+          this.certificateImageList.push({ name: 'certificateImage', url: certificateImage })
         }
       }, 200)
     },
@@ -190,6 +239,20 @@ export default {
     setParamToFormData() {
       return this.paramList.filter(item => item.paramContent !== '' && item.paramName !== '')
     },
+
+    handleRadioChange(index) {
+      if (index === 1 && this.certificateImageList.length <= 0) {
+        this.$message.warning('请先上传授权牌')
+        this.formData.addQrCodeFlag = 0
+        return
+      }
+    },
+
+    authCardChange(current) {
+      console.log(current)
+      this.formData.addTemplateType = current
+    },
+
     // 添加一栏参数
     handleAddParam() {
       this.paramsCount += 1
@@ -203,14 +266,41 @@ export default {
       this.paramsCount -= 1
       this.paramList.splice(index, 1)
     },
-    // 图片上传成功 产品图片
-    imageUploadSuccess1(data) {
-      this.formData.productImage = data.data
+
+    // 产品图片上传
+    beforeProductImageUpload(file) {
+      const flag = file.size / 1024 / 1024 < 1
+      if (!flag) {
+        this.$message.error('上传产品图片大小不能超过 1MB!')
+      }
+      return flag
+    },
+    uploadProductImageSuccess({ response, file, fileList }) {
+      this.productImageList = fileList
+      this.formData.productImage = response.data
+    },
+    handleProductImageRemove({ file, fileList }) {
+      this.productImageList = fileList
+      this.formData.productImage = ''
+    },
+    // 授权牌照上传
+    beforeCertificateImageUpload(file) {
+      const flag = file.size / 1024 / 1024 < 1
+      if (!flag) {
+        this.$message.error('上传授权牌图片大小不能超过 1MB!')
+      }
+      return flag
+    },
+    uploadCertificateImageSuccess({ response, file, fileList }) {
+      this.certificateImageList = fileList
+      this.formData.certificateImage = response.data
     },
-    // 图片上传成功 授权牌照
-    imageUploadSuccess2(data) {
-      this.formData.certificateImage = data.data
+    handleCertificateImageRemove({ file, fileList }) {
+      this.certificateImageList = fileList
+      this.formData.certificateImage = ''
+      this.formData.addQrCodeFlag = 0
     },
+
     setParamList(data) {
       this.paramList = data.paramList
     },
@@ -242,7 +332,7 @@ export default {
   }
 }
 .addForm {
-  width: 500px;
+  width: 800px;
   margin: 0 auto;
   margin-top: 80px;
 }

+ 1 - 2
src/views/authentic/product/index.vue

@@ -35,8 +35,6 @@
       </el-select>
       <el-button type="primary" icon="el-icon-search" @click="handleFilter">查询</el-button>
       <el-button v-if="isProxy" icon="el-icon-edit" type="primary" @click="$_navigationTo(`add?id=${listQuery.authId}`)">添加</el-button>
-      <el-button type="primary" icon="el-icon-download" @click="handleFilter">一键下载授权牌</el-button>
-      <el-button type="primary" icon="el-icon-download" @click="handleFilter">一键下载二维码</el-button>
     </div>
     <!-- 表格区域 -->
     <el-table
@@ -186,6 +184,7 @@ export default {
   },
 
   methods: {
+
     // 添加
     handleAddPro() {
       this.$router.push('add')

+ 158 - 0
src/views/authentic/review/auth/authDetail.vue

@@ -0,0 +1,158 @@
+<template>
+  <div v-if="!isLoading" class="club-edit">
+    <el-form ref="formRef" class="club-edit-form" label-width="120px" :model="formData" :rules="formRules">
+      <el-form-item label="机构名称:">
+        <span>{{ authInfo.authParty }}</span>
+      </el-form-item>
+      <el-form-item label="所在地区:">
+        <span>{{ authInfo.area }}</span>
+      </el-form-item>
+      <el-form-item label="详细地址:">
+        <span>{{ authInfo.address }}</span>
+      </el-form-item>
+      <el-form-item label="经纬度:">
+        <span>{{ authInfo.lngAndLat }}</span>
+      </el-form-item>
+      <el-form-item label="联系方式:" prop="mobile">
+        <span>{{ authInfo.mobile }}</span>
+      </el-form-item>
+      <el-form-item label="机构logo:">
+        <el-image
+          style="width: 140px; height: 140px"
+          :src="authInfo.logo"
+        />
+      </el-form-item>
+      <el-form-item label="轮播图:">
+        <el-image
+          v-for="(image,index) in authInfo.bannerList"
+          :key="index"
+          style="width: 140px; height: 140px;margin-right: 16px;"
+          :src="image"
+          :preview-src-list="imgList"
+        />
+      </el-form-item>
+
+      <!-- 审核表单 -->
+      <el-form-item label="审核状态:">
+        <el-radio-group v-model="formData.auditStatus">
+          <el-radio :label="1">通过</el-radio>
+          <el-radio :label="0">不通过</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item v-if="formData.auditStatus!==1" prop="invalidReason" label="原因:">
+        <el-input v-model="formData.invalidReason" type="textarea" placeholder="请说明原因" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="info" @click="$_back">返回</el-button>
+        <el-button type="primary" @click="submit">提交</el-button>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+// import Location from '@/components/location'
+import { getAuthFormData, auditAuth } from '@/api/auth'
+import { mapGetters } from 'vuex'
+
+export default {
+
+  data() {
+    return {
+      isLoading: false,
+
+      authId: '',
+
+      formData: {
+        auditBy: '', // 审核人id
+        authId: '', // 机构id
+        auditStatus: 1, // 审核状态
+        invalidReason: '' // 审核信息
+      },
+
+      formRules: {
+        invalidReason: { required: true, message: '不通过原因不能为空', tigger: 'blur' }
+      },
+
+      authInfo: {
+        address: '',
+        area: '',
+        authId: '',
+        authParty: '',
+        bannerList: '',
+        cityId: '',
+        lngAndLat: '',
+        logo: '',
+        mobile: '',
+        provinceId: '',
+        townId: ''
+      },
+
+      // 预览图片
+      imgList: []
+    }
+  },
+  computed: {
+    ...mapGetters(['authUserId'])
+  },
+  created() {
+    this.authId = this.formData.authId = this.$route.query.authId
+    this.getDetail()
+  },
+  methods: {
+    // 数据回显
+    getDetail() {
+      getAuthFormData({ authId: this.authId }).then(res => {
+        this.authInfo.address = res.data.address
+        this.authInfo.area = res.data.area
+        this.authInfo.authId = res.data.authId
+        this.authInfo.authParty = res.data.authParty
+        this.authInfo.bannerList = this.imgList = res.data.bannerList
+        this.authInfo.cityId = res.data.cityId
+        this.authInfo.lngAndLat = res.data.lngAndLat
+        this.authInfo.logo = res.data.logo
+        this.authInfo.mobile = res.data.mobile
+        this.authInfo.provinceId = res.data.provinceId
+        this.authInfo.townId = res.data.townId
+      })
+    },
+    // 提交审核信息
+    submit() {
+      this.$refs.formRef.validate(valid => {
+        if (valid) {
+          this.isLoading = true
+          // 指定审核人
+          this.formData.auditBy = this.authUserId
+          // 提交审核信息
+          auditAuth(this.formData).then(res => {
+            if (res.code !== 0) return
+            this.$message.success(res.data)
+            this.$store.dispatch('tagsView/delView', this.$route)
+            this.$router.back()
+          }).finally(() => {
+            this.isLoading = false
+          })
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.club-edit {
+  margin-bottom: 80px;
+}
+
+.club-edit-form {
+  width: 600px;
+  margin: 0 auto;
+  margin-top: 80px;
+}
+.submit-btn {
+  text-align: center;
+  .el-button {
+    width: 140px;
+  }
+}
+</style>

+ 2 - 2
src/views/authentic/review/auth/authList.vue

@@ -104,10 +104,10 @@
             size="mini"
             style="margin-right:5px"
             icon="el-icon-s-check"
-            @click="handleShowDialog(row)"
+            @click="$_navigationTo(`auth-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(`shop-list?authId=${row.authId}`)">设备认证审核</el-button>
+            <el-button icon="el-icon-s-shop" type="primary" size="mini" @click="$_navigationTo(`auth-shop-list?authId=${row.authId}`)">设备认证审核</el-button>
           </el-badge>
         </template>
       </el-table-column>

+ 3 - 3
src/views/authentic/review/auth/shopDetail.vue

@@ -104,8 +104,8 @@ export default {
             if (res.code !== 0) return
             this.$message.success(res.data)
             this.$store.dispatch('tagsView/delView', this.$route)
-            this.$router.replace(`/review/auth/shop-list?authId=${this.authId}`)
-            this.setMessageState({ id: parseInt(this.formData.productId), type: 2 })
+            this.$router.back()
+            // this.setMessageState({ id: parseInt(this.formData.productId), type: 2 })
           }).finally(() => {
             this.isLoading = false
           })
@@ -118,7 +118,7 @@ export default {
 
 <style lang="scss" scoped>
 .shop-detail{
-  height: 100vh;
+  margin-bottom: 80px;
   font-size: 14px;
   color: #444;
   .params-list{

+ 1 - 2
src/views/authentic/review/auth/shopList.vue

@@ -85,8 +85,7 @@
       </el-table-column>
       <el-table-column label="操作" width="240px" align="center">
         <template slot-scope="{row}">
-          <el-button v-if="row.auditStatus === 2" type="primary" icon="el-icon-s-check" size="mini" @click="$_navigationTo(`shop-detail?id=${row.productId}&authId=${listQuery.authId}`)">审核</el-button>
-          <span v-else class="status success el-icon-check">&nbsp;已审核</span>
+          <el-button v-if="row.auditStatus === 2" type="primary" icon="el-icon-s-check" size="mini" @click="$_navigationTo(`auth-shop-detail?id=${row.productId}&authId=${listQuery.authId}`)">审核</el-button>          <span v-else class="status success el-icon-check">&nbsp;已审核</span>
         </template>
       </el-table-column>
     </el-table>

+ 0 - 1
src/views/authentic/review/doc/articleDetail.vue

@@ -83,7 +83,6 @@ export default {
               type: 'success',
               duration: 1000
             })
-            // 如果保存文章成功就要关闭当前页面
             this.$store.dispatch('tagsView/delView', this.$route)
             this.$router.back()
           })

+ 1 - 1
src/views/authentic/review/doc/articleList.vue

@@ -90,7 +90,7 @@
             size="mini"
             style="margin-right:5px"
             icon="el-icon-s-check"
-            @click="$_navigationTo(`/review/doc/article/detail?articleId=${row.articleId}`)"
+            @click="$_navigationTo(`doc-article-detail?articleId=${row.articleId}`)"
           >审核</el-button>
           <span v-else class="status success el-icon-check">&nbsp;已审核</span>
         </template>

+ 1 - 1
src/views/authentic/review/doc/imageList.vue

@@ -83,7 +83,7 @@
             size="mini"
             style="margin-right:5px"
             icon="el-icon-s-check"
-            @click="$_navigationTo(`/review/doc/image/detail?imageId=${row.imageId}`)"
+            @click="$_navigationTo(`doc-image-detail?imageId=${row.imageId}`)"
           >审核</el-button>
           <span v-else class="status success el-icon-check">&nbsp;已审核</span>
         </template>

+ 4 - 4
src/views/authentic/review/doc/index.vue

@@ -88,7 +88,7 @@
               type="primary"
               icon="el-icon-tickets"
               size="mini"
-              @click="$_navigationTo(`/review/doc/article?authUserId=${row.authUserId}`)"
+              @click="$_navigationTo(`doc-article-list?authUserId=${row.authUserId}`)"
             >文章</el-button>
           </el-badge>
           <el-badge :hidden="row.imageWaitNum === 0" :value="row.imageWaitNum" :max="99">
@@ -96,7 +96,7 @@
               type="primary"
               icon="el-icon-picture-outline"
               size="mini"
-              @click="$_navigationTo(`/review/doc/image?authUserId=${row.authUserId}`)"
+              @click="$_navigationTo(`doc-image-list?authUserId=${row.authUserId}`)"
             >图片</el-button>
           </el-badge>
           <el-badge :hidden="row.videoWaitNum === 0" :value="row.videoWaitNum" :max="99">
@@ -104,7 +104,7 @@
               type="primary"
               icon="el-icon-video-camera"
               size="mini"
-              @click="$_navigationTo(`/review/doc/video?authUserId=${row.authUserId}`)"
+              @click="$_navigationTo(`doc-video-list?authUserId=${row.authUserId}`)"
             >视频</el-button>
           </el-badge>
           <el-badge :hidden="row.fileWaitNum === 0" :value="row.fileWaitNum" :max="99">
@@ -112,7 +112,7 @@
               type="primary"
               icon="el-icon-document-copy"
               size="mini"
-              @click="$_navigationTo(`/review/doc/file?authUserId=${row.authUserId}`)"
+              @click="$_navigationTo(`doc-file-list?authUserId=${row.authUserId}`)"
             >文件</el-button>
           </el-badge>
         </template>

+ 136 - 86
src/views/authentic/review/doctor/doctorDetail.vue

@@ -1,118 +1,142 @@
 <template>
   <div class="doctor-edit">
-    <el-form class="doctor-edit-form" label-width="130px" :model="formData" :rules="rules">
-      <el-form-item label="医师姓名:" prop="name">
-        <span>{{ formData.name }}</span>
+    <el-form ref="formRef" class="doctor-edit-form" label-width="140px" :model="formData" :rules="formRules">
+      <el-form-item label="医师姓名:">
+        <span>{{ doctorInfo.doctorName }}</span>
       </el-form-item>
-      <el-form-item label="从业资格证编号:" prop="name">
-        <span>{{ formData.name }}</span>
+      <el-form-item label="从业资格证编号:">
+        <span>{{ doctorInfo.certificateNo }}</span>
       </el-form-item>
-      <el-form-item label="所在机构:" prop="name">
-        <span>{{ formData.name }}</span>
+      <el-form-item label="所在机构:" prop="clubName">
+        <span>{{ doctorInfo.clubName }}</span>
+      </el-form-item>
+      <el-form-item label="医师照片:" prop="doctorImage">
+        <el-image
+          style="width: 140px; height: 140px"
+          :src="doctorInfo.doctorImage"
+        />
       </el-form-item>
       <el-form-item label="轮播图:" prop="banner">
-        <img src="https://picsum.photos/200/200" alt="">
-        <img src="https://picsum.photos/200/200" alt="">
-        <img src="https://picsum.photos/200/200" alt="">
+        <el-image
+          v-for="(image,index) in doctorInfo.bannerList"
+          :key="index"
+          style="width: 140px; height: 140px"
+          :src="image"
+        />
       </el-form-item>
 
-      <el-form-item label="具备操作资格设备:">
-        <div class="section" />
-
+      <el-form-item label="具备操作资格设备:" prop="equipment">
+        <div class="device-section">
+          <div v-for="(equipment, index) in doctorInfo.equipmentList" :key="index" class="section">
+            <el-form label-width="90px">
+              <el-form-item label="设备名称:">
+                <span>{{ equipment.equipmentName }}</span>
+              </el-form-item>
+              <el-form-item label="所属品牌:">
+                <span>{{ equipment.brand }}</span>
+              </el-form-item>
+              <el-form-item label="设备图片:">
+                <el-image
+                  style="width: 140px; height: 140px"
+                  :src="equipment.image"
+                />
+              </el-form-item>
+            </el-form>
+          </div>
+        </div>
       </el-form-item>
 
+      <!-- 审核表单 -->
+      <el-form-item label="审核状态:">
+        <el-radio-group v-model="formData.auditStatus">
+          <el-radio :label="1">通过</el-radio>
+          <el-radio :label="0">不通过</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item v-if="formData.auditStatus!==1" prop="invalidReason" label="原因:">
+        <el-input v-model="formData.invalidReason" type="textarea" placeholder="请说明原因" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="info" @click="$_back">返回</el-button>
+        <el-button type="primary" @click="submit">提交</el-button>
+      </el-form-item>
     </el-form>
-    <div class="submit-btn">
-      <el-button type="primary" @click="submit">通过</el-button>
-      <el-button type="warning" @click="$_back()">不通过</el-button>
-    </div>
   </div>
 </template>
 
 <script>
 import { mapGetters } from 'vuex'
+import { doctorFormData, doctorAudit } from '@/api/doctor'
+
 export default {
   data() {
     return {
-      dialogMapVisible: false,
+      isRequest: true,
+      doctorId: '',
       point: {},
-      value: [],
-      options: [{
-        value: 'zhinan',
-        label: '指南',
-        children: [{
-          value: 'shejiyuanze',
-          label: '设计原则',
-          children: [{
-            value: 'yizhi',
-            label: '一致'
-          }, {
-            value: 'fankui',
-            label: '反馈'
-          }, {
-            value: 'xiaolv',
-            label: '效率'
-          }, {
-            value: 'kekong',
-            label: '可控'
-          }]
-        }, {
-          value: 'daohang',
-          label: '导航',
-          children: [{
-            value: 'cexiangdaohang',
-            label: '侧向导航'
-          }, {
-            value: 'dingbudaohang',
-            label: '顶部导航'
-          }]
-        }]
-      }],
       disabled: false,
-      formData: {
-        name: '',
-        address: '',
-        fullAddress: '',
-        point: '',
-        mobile: '',
-        logoImage: '',
-        banner: ''
+      doctorInfo: {
+        doctorName: '',
+        certificateNo: '',
+        clubName: '',
+        bannerList: '',
+        doctorImage: '',
+        equipmentList: ''
       },
-      rules: {
-        name: [{ required: true, message: '机构名称不能为空', trigger: ['blur', 'change'] }],
-        address: [{ required: true, message: '地址不能为空', trigger: 'change' }],
-        fullAddress: [{ required: true, message: '详细不能为空', trigger: ['blur', 'change'] }],
-        point: [{ required: true, message: '地址坐标不能为空', trigger: ['blur', 'change'] }],
-        mobile: [{ required: true, message: '联系方式不能为空', trigger: ['blur', 'change'] }],
-        logoImage: [{ required: true, message: '请上传机构logo', trigger: 'change' }],
-        banner: [{ required: true, message: '请至少上传一张banner图片', trigger: 'change' }]
-
+      formData: {
+        auditBy: '', // 审核人id
+        doctorId: '', // 商品id
+        auditStatus: 1, // 商品审核状态
+        invalidReason: '' // 审核信息
       },
-      // logo图片列表
-      logoList: [],
-      // banner图片列表
-      bannerList: [],
-      // 资格仪器列表
-      deviceList: []
+      formRules: {
+        invalidReason: { required: true, message: '不通过原因不能为空', tigger: 'blur' }
+      }
     }
   },
   computed: {
-    ...mapGetters(['token']),
-    // 图片上传
-    action() {
-      return process.env.VUE_APP_UPLOAD_API + '/upload/image'
-    },
-    headers() {
-      return {
-        'X-Token': this.token
-      }
-    }
+    ...mapGetters(['authUserId'])
   },
   created() {
-
+    this.doctorId = this.formData.doctorId = parseInt(this.$route.query.id)
+    this.initFormData()
   },
   methods: {
-    submit() {}
+    // 表单数据回显
+    initFormData() {
+      doctorFormData({ doctorId: this.doctorId }).then(res => {
+        this.setFormData(res.data)
+      })
+    },
+    // 设置表单数据
+    setFormData(data) {
+      this.doctorInfo.doctorName = data.doctorName
+      this.doctorInfo.certificateNo = data.certificateNo
+      this.doctorInfo.clubName = data.clubName
+      this.doctorInfo.bannerList = data.bannerList
+      this.doctorInfo.doctorImage = data.doctorImage
+      this.doctorInfo.equipmentList = data.equipmentList
+    },
+
+    // 提交审核信息
+    submit() {
+      this.$refs.formRef.validate(valid => {
+        if (valid) {
+          this.isLoading = true
+          // 指定审核人
+          this.formData.auditBy = this.authUserId
+          // 提交审核信息
+          doctorAudit(this.formData).then(res => {
+            if (res.code !== 0) return
+            this.$message.success(res.data)
+            this.$store.dispatch('tagsView/delView', this.$route)
+            this.$router.back()
+          }).finally(() => {
+            this.isLoading = false
+          })
+        }
+      })
+    }
   }
 }
 </script>
@@ -123,7 +147,7 @@ export default {
 }
 
 .doctor-edit-form {
-  width: 600px;
+  width: 650px;
   margin: 0 auto;
   margin-top: 80px;
 }
@@ -134,4 +158,30 @@ export default {
   }
 }
 
+.device-section {
+  .section {
+    position: relative;
+    border: 1px solid #eee;
+    padding: 25px 25px 0 16px;
+    margin-bottom: 16px;
+    .remove {
+      position: absolute;
+      right: 6px;
+      top: 6px;
+      font-size: 14px;
+      cursor: pointer;
+      background: #f56c6c;
+      color: #fff;
+      padding: 2px;
+      border-radius: 50%;
+      transition: all 0.2s;
+      &:hover {
+        background: red;
+      }
+    }
+  }
+  .el-form-item {
+    padding-bottom: 25px;
+  }
+}
 </style>

+ 204 - 0
src/views/authentic/review/doctor/doctorList.vue

@@ -0,0 +1,204 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <span>医师姓名:</span>
+      <el-input v-model="listQuery.doctorName" placeholder="医师姓名" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
+      <span>从业资格证编号:</span>
+      <el-input v-model="listQuery.certificateNo" placeholder="从业资格证编号" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
+      <span>审核状态:</span>
+      <el-select
+        v-model="listQuery.auditStatus"
+        placeholder="审核状态"
+        clearable
+        style="width: 200px"
+        class="filter-item"
+        @change="getList"
+      >
+        <el-option label="全部" value="" />
+        <el-option label="待审核" :value="2" />
+        <el-option label="审核通过" :value="1" />
+        <el-option label="审核未通过" :value="0" />
+      </el-select>
+      <el-button type="primary" icon="el-icon-search" @click="getList">查询</el-button>
+    </div>
+    <!-- 表格区域 -->
+    <el-table
+      :key="tableKey"
+      v-loading="listLoading"
+      :data="list"
+      border
+      fit
+      highlight-current-row
+      style="width: 100%;"
+      header-row-class-name="tableHeader"
+    >
+      <el-table-column label="序号" :index="indexMethod" type="index" align="center" width="80" />
+      <el-table-column label="医生姓名" align="center" prop="doctorName" />
+      <el-table-column label="从业资格证编号" align="center" prop="certificateNo" />
+
+      <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>
+        </template>
+      </el-table-column>
+
+      <el-table-column label="上线状态" width="140px" align="center">
+        <template slot-scope="{row}">
+          <!-- 只有审核通过了才能操作上下线 auditStatus :审核状态 -->
+          <template v-if="row.auditStatus === 1">
+            <template v-if="row.status === 0">
+              <span style="margin-right:10px;" class="status danger">已下线</span>
+            </template>
+            <template v-else>
+              <span style="margin-right:10px;" class="status success ">已上线</span>
+            </template>
+          </template>
+          <template v-else>
+            <!-- <el-tag type="warning">待上线</el-tag> -->
+            <span style="margin-right:10px;" class="status warning">待上线</span>
+          </template>
+        </template>
+      </el-table-column>
+      <el-table-column label="审核人" align="center">
+        <template slot-scope="{row}">
+          <span v-if="row.auditStatus!==2">{{ row.auditBy }}</span>
+          <span v-else>—</span>
+        </template>
+      </el-table-column>
+
+      <!-- <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 }">
+          <el-button type="primary" size="mini" @click="$_navigationTo(`doctor-detail?id=${row.doctorId}`)">
+            审核
+          </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 Pagination from '@/components/Pagination' // secondary package based on el-pagination
+import { mapGetters } from 'vuex'
+import { formatDate } from '@/utils'
+import { fetchDoctorList, removeDoctor, doctorStatusChange } from '@/api/doctor'
+
+export default {
+  components: { Pagination },
+  filters: {
+    formatTime(time) {
+      if (!time) {
+        return ''
+      }
+      return formatDate(time, 'yyyy-MM-DD HH:mm:ss')
+    }
+  },
+  data() {
+    return {
+      listLoading: false,
+      tableKey: 0,
+      total: 0,
+      listQuery: {
+        authUserId: '',
+        listType: 2,
+        doctorName: '',
+        auditStatus: '',
+        certificateNo: '',
+        status: '',
+        pageNum: 1,
+        pageSize: 10
+      },
+      list: []
+    }
+  },
+  computed: {
+    ...mapGetters(['authUserId', 'proxyInfo'])
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    // 获取列表
+    getList() {
+      this.listQuery.authUserId = this.$route.query.authUserId
+
+      console.log(this.listQuery.authUserId)
+      fetchDoctorList(this.listQuery).then(res => {
+        console.log(res)
+        this.list = res.data.list
+        this.total = res.data.total
+      })
+    },
+    // 修改状态
+    handleChangeStatus(row) {
+      const status = row.status === 1 ? 0 : 1
+
+      doctorStatusChange({ doctorId: row.doctorId, status }).then(res => {
+        this.$message.success('状态修改成功')
+        this.getList()
+      })
+    },
+    // 删除
+    async handleRemoveDoctor(row) {
+      const text = await this.$confirm('确认删除该医师信息吗?删除后不可恢复', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).catch(() => {
+        this.$message.info('已取消操作')
+      })
+      if (text !== 'confirm') return
+
+      removeDoctor({ doctorId: row.doctorId }).then(res => {
+        this.$message.success('删除成功')
+        this.getList()
+      })
+    },
+    // 表格索引
+    indexMethod(index) {
+      return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.filter-container{
+  span{
+    display: inline-block;
+    margin-bottom: 10px;
+    vertical-align: middle;
+    font-size: 14px;
+  }
+  .el-button{
+    display: inline-block;
+    margin-bottom: 10px;
+    vertical-align: middle;
+  }
+  .el-input,.el-select{
+    margin-right: 10px;
+    margin-left: 10px;
+  }
+}
+</style>

+ 108 - 92
src/views/authentic/review/doctor/index.vue

@@ -1,141 +1,153 @@
 <template>
   <div class="app-container">
+    <!-- 搜索区域 -->
     <div class="filter-container">
-      <span>医师姓名:</span>
-      <el-input v-model="listQuery.productName" placeholder="医师姓名" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
-      <span>审核状态:</span>
+      <span>供应商名称:</span>
+      <el-input
+        v-model="listQuery.shopName"
+        placeholder="供应商名称"
+        style="width: 200px"
+        class="filter-item"
+        @keyup.enter.native="getList"
+      />
+      <span>供应商类型:</span>
       <el-select
-        v-model="listQuery.auditStatus"
-        placeholder="审核状态"
+        v-model="listQuery.shopType"
+        placeholder="供应商类型"
         clearable
         style="width: 200px"
         class="filter-item"
         @change="getList"
       >
-        <el-option label="全部" value="" />
-        <el-option label="待审核" :value="2" />
-        <el-option label="审核通过" :value="1" />
-        <el-option label="审核未通过" :value="0" />
+        <el-option label="所有类型" value="" />
+        <el-option label="代理商" :value="2" />
+        <el-option label="品牌方" :value="1" />
       </el-select>
-      <span>上线状态:</span>
+      <span>手机号:</span>
+      <el-input
+        v-model="listQuery.mobile"
+        placeholder="手机号"
+        style="width: 200px"
+        class="filter-item"
+        @keyup.enter.native="getList"
+      />
+      <span>审核状态:</span>
       <el-select
-        v-model="listQuery.status"
-        placeholder="上线状态"
+        v-model="listQuery.lowerAuditStatus"
+        placeholder="审核状态"
         clearable
         style="width: 200px"
         class="filter-item"
         @change="getList"
       >
         <el-option label="全部" value="" />
-        <el-option label="已上线" :value="1" />
-        <el-option label="待上线" :value="2" />
-        <el-option label="未上线" :value="0" />
+        <el-option label="已完成审核" :value="1" />
+        <el-option label="未完成审核" :value="0" />
       </el-select>
+      <span>联系人:</span>
+      <el-input
+        v-model="listQuery.linkMan"
+        placeholder="联系人"
+        style="width: 200px"
+        class="filter-item"
+        @keyup.enter.native="getList"
+      />
       <el-button type="primary" icon="el-icon-search" @click="getList">查询</el-button>
     </div>
+    <!-- 搜索区域END -->
     <!-- 表格区域 -->
     <el-table
-      :key="tableKey"
       v-loading="listLoading"
       :data="list"
+      style="width: 100%"
       border
       fit
       highlight-current-row
-      style="width: 100%;"
-      header-row-class-name="tableHeader"
+      cell-class-name="table-cell"
     >
-      <el-table-column label="序号" :index="indexMethod" type="index" align="center" width="80" />
-      <el-table-column label="医生姓名" align="center" prop="productName" />
-      <el-table-column label="从业资格证编号" align="center" prop="snCode" />
-
-      <el-table-column label="审核状态" width="220px" align="center">
+      <el-table-column :index="indexMethod" label="序号" type="index" width="80" align="center" />
+      <el-table-column prop="name" label="供应商名称" align="center" />
+      <el-table-column label="供应商类型" width="150px" 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>
-        </template>
-      </el-table-column>
-
-      <el-table-column label="上线状态" width="140px" align="center">
-        <template slot-scope="{row}">
-          <!-- 只有审核通过了才能操作上下线 auditStatus :审核状态 -->
-          <template v-if="row.auditStatus === 1">
-            <template v-if="row.status === 0">
-              <span style="margin-right:10px;" class="status danger">已下线</span>
-              <el-button v-if="isProxy" type="primary" size="mini" @click="handleChangeStatus(row)">上线</el-button>
-            </template>
-            <template v-else>
-              <span style="margin-right:10px;" class="status success ">已上线</span>
-              <el-button v-if="isProxy" type="info" size="mini" @click="handleChangeStatus(row)">下线</el-button>
-            </template>
-          </template>
-          <template v-else>
-            <!-- <el-tag type="warning">待上线</el-tag> -->
-            <span style="margin-right:10px;" class="status warning">待上线</span>
-          </template>
+          <span v-if="row.shopType === 1">品牌方</span>
+          <span v-if="row.shopType === 2">代理商</span>
         </template>
       </el-table-column>
-      <el-table-column label="创建时间" class-name="status-col" width="300px" align="center">
-        <template slot-scope="{row}">
-          <span>{{ row.createTime | formatTime }}</span>
+      <el-table-column prop="mobile" label="手机号" width="200px" align="center" />
+      <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>
         </template>
       </el-table-column>
-
-      <!-- <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}">
-          <el-button type="default" size="mini" @click="$_navigationTo(`detail?id=${row.productId}`)">
-            审核
-          </el-button>
+      <el-table-column label="操作" width="240px" 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(`doctor-list?authUserId=${row.authUserId}`)"
+            >医师认证审核</el-button>
+          </el-badge>
         </template>
       </el-table-column>
     </el-table>
+    <!-- 表格区域END -->
     <!-- 页码 -->
-    <pagination v-show="total>0" :total="total" :page.sync="listQuery.pageNum" :limit.sync="listQuery.pageSize" @pagination="getList" />
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="getList(listQuery)"
+    />
   </div>
 </template>
 
 <script>
-import Pagination from '@/components/Pagination' // secondary package based on el-pagination
+import { fetchSupplierList } from '@/api/supplier'
+import Pagination from '@/components/Pagination'
 export default {
   components: { Pagination },
   data() {
     return {
-      listLoading: false,
-      tableKey: 0,
-      total: 0,
       listQuery: {
-        status: '',
-        auditStatus: '',
-        authId: '',
-        productName: '',
-        snCode: '',
-        pageNum: 1,
-        pageSize: 10
+        listType: 4,
+        brandId: '', // 品牌id
+        linkMan: '', // 联系人
+        mobile: '', // 手机号
+        pageNum: 0, // 页码
+        pageSize: 10, // 分页大小
+        shopName: '', // 供应商名称
+        shopType: '', // 供应商类型
+        lowerAuditStatus: ''
       },
-      list: []
+      listLoading: false,
+      list: [],
+      total: 0
     }
   },
+  created() {
+    this.getList()
+  },
   methods: {
-    getList() {},
-    handleChangeStatus() {},
-    handleRemoveDoctor() {},
+    // 过滤列表
+    handleFilter() {},
+    // 获取供应商列表
+    getList() {
+      this.listLoading = true
+      fetchSupplierList(this.listQuery)
+        .then(res => {
+          if (res.code !== 0) return
+          this.list = res.data.list
+          this.total = res.data.total
+        })
+        .finally(() => {
+          this.listLoading = false
+        })
+    },
     indexMethod(index) {
       return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1
     }
@@ -144,21 +156,25 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-.filter-container{
-  span{
+.filter-container {
+  span {
     display: inline-block;
     margin-bottom: 10px;
     vertical-align: middle;
     font-size: 14px;
   }
-  .el-button{
+  .el-button {
     display: inline-block;
     margin-bottom: 10px;
     vertical-align: middle;
   }
-  .el-input,.el-select{
+  .el-input,
+  .el-select {
     margin-right: 10px;
     margin-left: 10px;
   }
 }
+.el-table .cell {
+  overflow: visible;
+}
 </style>

+ 47 - 9
src/views/authentic/supplier/add.vue

@@ -39,6 +39,19 @@
         <el-input v-model="formData1.linkMan" placeholder="请输入联系人" />
       </el-form-item>
 
+      <!-- 代理商logo -->
+      <transition name="fade">
+        <el-form-item v-if="formData1.shopType === 2" label="代理商logo:" prop="logo">
+          <el-input v-show="false" v-model="formData1.logo" />
+          <upload-image-t
+            tip="建议尺寸:200px * 200px"
+            :image-list="logoList"
+            :before-upload="beforeLogoImageUpload"
+            @success="uploadLogoImageSuccess"
+            @remove="handleLogoImageRemove"
+          />
+        </el-form-item>
+      </transition>
       <transition name="fade">
         <el-form-item v-if="formData1.shopType === 2" label="代理品牌:" prop="shopInfo" class="brand-list">
           <template v-if="supplierBrands !== []">
@@ -79,9 +92,9 @@
 
       <!-- 公众号信息 -->
       <el-form-item label="微信公众号:">
-        <el-select v-model="formData1.appType" placeholder="请选择微信公众号类型" style="width: 100%">
-          <el-option label="服务号" :value="1" />
-          <el-option label="订阅号" :value="0" />
+        <el-select v-model="formData1.wxAccountType" placeholder="请选择微信公众号类型" style="width: 100%">
+          <el-option label="服务号" :value="2" />
+          <el-option label="订阅号" :value="1" />
         </el-select>
       </el-form-item>
       <el-form-item label="appID:">
@@ -225,13 +238,14 @@
 <script>
 import UploadImage from '../components/uploadImage'
 import UploadFile from '../components/uploadFile'
+import UploadImageT from '@/components/UploadImage'
 import { mapGetters } from 'vuex'
 import { isMobile } from '@/utils/validate'
 import { fetchBrandList } from '@/api/brand'
 import { addSupplier } from '@/api/supplier'
 
 export default {
-  components: { UploadImage, UploadFile },
+  components: { UploadImage, UploadFile, UploadImageT },
   data() {
     const validMobile = (rule, value, callback) => {
       if (!isMobile(value)) {
@@ -261,10 +275,11 @@ export default {
         securityLink: '', // 官网认证链接
         shopStatus: 1, // 供应商状态,
         shopInfo: '',
-        appType: '',
+        wxAccountType: 2,
         appId: '',
         appSecret: '',
-        qrCodeImage: '' // 微信公众号二维码
+        qrCodeImage: '', // 微信公众号二维码
+        logo: '' // 代理商logo
       },
       // 表单2
       formData2: {
@@ -297,7 +312,8 @@ export default {
         statementContent: { required: true, message: '声明内容不能为空', tigger: 'change' }, // 声明内容
         statementFileId: { required: true, message: '声明文件不能为空', tigger: 'change', type: 'number' }, // 声明文件id
         statementImage: { required: true, message: '声明图片不能为空', tigger: 'change' }, // 声明图片
-        statementLink: { required: true, message: '声明链接不能为空', tigger: 'change' } // 声明链接
+        statementLink: { required: true, message: '声明链接不能为空', tigger: 'change' }, // 声明链接,
+        logo: { required: true, message: '代理商logo不能为空', tigger: 'change' }
         // ewmUrl: { required: true, message: '微信公众号二维码不能为空', tigger: 'change' }
       },
       // 上传的文件列表
@@ -305,6 +321,7 @@ export default {
       fileList2: [],
       fileList3: [],
       fileList4: [], // 文件
+      logoList: [],
       ewmUrl: []
     }
   },
@@ -368,7 +385,8 @@ export default {
         shopInfo: [],
         qrCodeImage: '',
         appId: '',
-        appSecret: ''
+        appSecret: '',
+        wxAccountType: ''
       }
       // 品牌方
       if (this.selectedShopType === 1) {
@@ -402,6 +420,7 @@ export default {
           }
         }
         result.shopInfo = this.supplierBrands
+        result.logo = this.formData1.logo
       }
       result.createBy = this.authUserId
       console.log(result)
@@ -603,6 +622,24 @@ export default {
     wxImageUploadRemove() {
       this.formData1.qrCodeImage = ''
     },
+
+    // 代理商logo上传
+    beforeLogoImageUpload(file) {
+      const flag = file.size / 1024 / 1024 < 1
+      if (!flag) {
+        this.$message.error('上传医师照片大小不能超过 1MB!')
+      }
+      return flag
+    },
+    uploadLogoImageSuccess({ response, file, fileList }) {
+      this.logoList = fileList
+      this.formData1.logo = response.data
+    },
+    handleLogoImageRemove({ file, fileList }) {
+      this.logoList = fileList
+      this.formData1.logo = ''
+    },
+
     // 重置表单1
     resetFormData1(shopType) {
       this.formData1 = {
@@ -616,7 +653,8 @@ export default {
         securityLink: '', // 官网认证链接
         shopStatus: 1, // 供应商状态,
         shopInfo: [],
-        qrCodeImage: ''
+        qrCodeImage: '',
+        logo: ''
       }
       this.fileList1 = []
       this.fileList2 = []

+ 47 - 8
src/views/authentic/supplier/edit.vue

@@ -43,6 +43,20 @@
         <el-input v-model="formData1.linkMan" placeholder="请输入联系人" />
       </el-form-item>
 
+      <!-- 代理商logo -->
+      <transition name="fade">
+        <el-form-item v-if="formData1.shopType === 2" label="代理商logo:" prop="logo">
+          <el-input v-show="false" v-model="formData1.logo" />
+          <upload-image-t
+            tip="建议尺寸:200px * 200px"
+            :image-list="logoList"
+            :before-upload="beforeLogoImageUpload"
+            @success="uploadLogoImageSuccess"
+            @remove="handleLogoImageRemove"
+          />
+        </el-form-item>
+      </transition>
+
       <transition name="fade">
         <el-form-item v-if="formData1.shopType === 2" ref="shopInfoRef" label="代理品牌:" prop="shopInfo" class="brand-list">
           <template v-if="supplierBrands !== []">
@@ -82,9 +96,9 @@
       </template>
       <!-- 公众号信息 -->
       <el-form-item label="微信公众号:">
-        <el-select v-model="formData1.appType" placeholder="请选择微信公众号类型" style="width: 100%">
-          <el-option label="服务号" :value="1" />
-          <el-option label="订阅号" :value="0" />
+        <el-select v-model="formData1.wxAccountType" placeholder="请选择微信公众号类型" style="width: 100%">
+          <el-option label="服务号" :value="2" />
+          <el-option label="订阅号" :value="1" />
         </el-select>
       </el-form-item>
       <el-form-item label="appID:">
@@ -229,13 +243,14 @@
 <script>
 import UploadImage from '../components/uploadImage'
 import UploadFile from '../components/uploadFile'
+import UploadImageT from '@/components/UploadImage'
 import { mapGetters } from 'vuex'
 import { isMobile } from '@/utils/validate'
 import { fetchBrandList } from '@/api/brand'
 import { addSupplier, getSupplierById } from '@/api/supplier'
 
 export default {
-  components: { UploadImage, UploadFile },
+  components: { UploadImage, UploadFile, UploadImageT },
   data() {
     const validMobile = (rule, value, callback) => {
       if (!isMobile(value)) {
@@ -268,10 +283,11 @@ export default {
         securityLink: '', // 官网认证链接
         shopStatus: 1, // 供应商状态,
         shopInfo: '',
-        appType: '',
+        wxAccountType: '',
         appId: '',
         appSecret: '',
-        qrCodeImage: '' // 公众号二维码
+        qrCodeImage: '', // 公众号二维码
+        logo: '' // 代理商logo
       },
       // 表单2
       formData2: {
@@ -304,13 +320,15 @@ export default {
         statementContent: { required: true, message: '声明内容不能为空', tigger: 'change' }, // 声明内容
         statementFileId: { required: true, message: '声明文件不能为空', tigger: 'change', type: 'number' }, // 声明文件id
         statementImage: { required: true, message: '声明图片不能为空', tigger: 'change' }, // 声明图片
-        statementLink: { required: true, message: '声明链接不能为空', tigger: 'change' } // 声明链接
+        statementLink: { required: true, message: '声明链接不能为空', tigger: 'change' }, // 声明链接
+        logo: { required: true, message: '代理商logo不能为空', tigger: 'change' }
       },
       // 上传的文件列表
       fileList1: [],
       fileList2: [],
       fileList3: [],
       fileList4: [], // 文件
+      logoList: [],
       ewmUrl: []
     }
   },
@@ -383,6 +401,7 @@ export default {
           this.excludeBrandList.push(item.brandId)
         })
         this.supplierBrands = data.shopInfo
+        this.logoList = [{ name: '', url: this.formData1.logo }]
       }
       // 如果存在公众号二维码
       if (this.formData1.qrCodeImage) {
@@ -426,7 +445,8 @@ export default {
         shopInfo: [],
         qrCodeImage: '',
         appId: '',
-        appSecret: ''
+        appSecret: '',
+        wxAccountType: ''
       }
       // 品牌方
       if (this.selectedShopType === 1) {
@@ -461,6 +481,7 @@ export default {
           }
         }
         result.shopInfo = this.supplierBrands
+        result.logo = this.formData1.logo
       }
       result.createBy = this.authUserId
       console.log(result)
@@ -680,6 +701,24 @@ export default {
     wxImageUploadRemove() {
       this.formData1.qrCodeImage = ''
     },
+
+    // 代理商logo上传
+    beforeLogoImageUpload(file) {
+      const flag = file.size / 1024 / 1024 < 1
+      if (!flag) {
+        this.$message.error('上传医师照片大小不能超过 1MB!')
+      }
+      return flag
+    },
+    uploadLogoImageSuccess({ response, file, fileList }) {
+      this.logoList = fileList
+      this.formData1.logo = response.data
+    },
+    handleLogoImageRemove({ file, fileList }) {
+      this.logoList = fileList
+      this.formData1.logo = ''
+    },
+
     // 重置表单1
     resetFormData1(shopType) {
       this.formData1 = {

+ 273 - 0
src/views/authentic/supplier/product/detail.vue

@@ -0,0 +1,273 @@
+<template>
+  <div v-loading="isLoading" class="addProduct">
+    <el-form ref="addFormRef" label-width="120px" class="addForm" :model="formData" :rules="rules">
+      <el-form-item label="设备名称:" prop="productName">
+        <el-input v-model="formData.productName" placeholder="请输入设备名称" disabled />
+      </el-form-item>
+
+      <el-form-item label="设备SN码:" prop="snCode">
+        <el-input v-model="formData.snCode" placeholder="请输入设备SN码" disabled />
+      </el-form-item>
+
+      <el-form-item v-if="shopType === 2" label="所属品牌:" prop="brandId">
+        <el-select v-model="formData.brandId" placeholder="请选择品牌" style="width: 100%" filterable disabled>
+          <el-option v-for="item in brandList" :key="item.id" :label="item.name" :value="item.id" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="设备图片:" prop="productImage">
+        <upload-image ref="uploadImageRef2" :file-list="fileList1" disabled @success="imageUploadSuccess1" />
+        <el-input v-model="formData.productImage" class="hiddenInput" />
+      </el-form-item>
+      <el-form-item label="授权牌:" prop="certificateImage">
+        <upload-image ref="uploadImageRef2" :file-list="fileList2" disabled @success="imageUploadSuccess2" />
+        <el-input v-model="formData.certificateImage" class="hiddenInput" />
+      </el-form-item>
+      <el-form-item label="相关参数:" prop="paramList">
+        <div v-for="(item, index) in paramList" :key="index" class="form-group paramsItem">
+          <el-input v-model="item.paramName" class="param-title" placeholder="参数名称" maxlength="10" disabled />
+          <el-input v-model="item.paramContent" class="param-info" placeholder="请输入参数信息" maxlength="50" disabled />
+          <span v-if="paramsCount > 4" class="closed el-icon-close" @click="handleRemoveParam(index)" />
+        </div>
+        <!-- <el-button type="primary" size="mini" @click="handleAddParam">添加参数</el-button> -->
+      </el-form-item>
+      <!-- <el-form-item label="上线状态:">
+        <el-select
+          v-model="formData.status"
+          placeholder="上架状态"
+          style="width: 100%"
+        >
+          <el-option label="上线" :value="1" />
+          <el-option label="下线" :value="0" />
+        </el-select>
+      </el-form-item>-->
+    </el-form>
+    <!-- <div class="submit-btn">
+      <el-button type="primary" @click="submit">保存</el-button>
+      <el-button type="warning" @click="$_back()">返回</el-button>
+    </div> -->
+  </div>
+</template>
+
+<script>
+import UploadImage from '../../components/uploadImage'
+import { saveProduct, getProductById } from '@/api/product'
+import { fetchBrandList } from '@/api/brand'
+import { mapGetters } from 'vuex'
+export default {
+  components: { UploadImage },
+  data() {
+    return {
+      isLoading: false,
+      paramsCount: 4,
+      formData: {
+        authUserId: '',
+        authId: '', //	授权id
+        certificateImage: '', //	授权牌照
+        createBy: '', //	创建人id
+        // 	设备参数列表
+        paramList: [],
+        productId: '', //	授权设备id
+        productImage: '', //	设备图片
+        productName: '', //	设备名称
+        snCode: '', //	设备SN码
+        brandId: ''
+      },
+      paramList: [],
+      brandList: [],
+      rules: {
+        certificateImage: [{ required: true, message: '授权牌照不能为空' }],
+        paramList: [{ required: true, message: '参数不能为空' }],
+        productImage: [{ required: true, message: '设备图片不能为空' }],
+        snCode: [{ required: true, message: 'SN码不能为空' }],
+        productName: [
+          { required: true, message: '设备名称不能为空' },
+          { max: 50, message: '字数在50字符以内' }
+        ]
+      },
+      fileList1: [],
+      fileList2: []
+    }
+  },
+  computed: {
+    ...mapGetters(['authUserId', 'proxyInfo', 'shopType', 'brandId'])
+  },
+  watch: {
+    paramList: {
+      deep: true,
+      handler: function() {
+        this.formData.paramList = this.setParamToFormData()
+      }
+    }
+  },
+  created() {
+    this.formData.productId = parseInt(this.$route.query.id)
+    this.formData.authUserId = this.proxyInfo?.authUserId || this.authUserId
+    this.initFormData()
+    if (this.shopType === 2) {
+      this.getBrandList()
+    }
+    // 如果供应商类型为品牌方,则自动设置品牌id
+    if (this.shopType === 1) {
+      this.formData.brandId = this.proxyInfo?.brandId || this.brandId || ''
+    }
+  },
+  methods: {
+    // 提交
+    submit() {
+      this.formData.paramList = this.setParamToFormData()
+      this.$refs.addFormRef.validate(valide => {
+        if (valide) {
+          this.save()
+        }
+      })
+    },
+    // 初始化表单数据
+    initFormData() {
+      this.isLoading = true
+      getProductById({ productId: this.formData.productId }).then(res => {
+        console.log(res)
+        // const { authId, certificateImage, paramList, productId, productImage, productName, snCode, status } = res.data
+        for (const key in res.data) {
+          if (Object.hasOwnProperty.call(res.data, key)) {
+            if (key !== 'paramList') {
+              this.formData[key] = res.data[key]
+            }
+          }
+        }
+        // 初始化参数
+        this.paramList = res.data.paramList
+        this.paramsCount = this.paramList.length
+        if (this.paramsCount < 4) {
+          this.initParamList(4 - this.paramsCount)
+        }
+        this.initImageList()
+        this.isLoading = false
+      })
+    },
+    // 获取品牌信息
+    getBrandList() {
+      fetchBrandList({ type: 3, authUserId: this.formData.authUserId }).then(res => {
+        console.log(res)
+        this.brandList = res.data
+      })
+    },
+    // 初始化上传图片列表
+    initImageList() {
+      setTimeout(() => {
+        const productImage = this.formData.productImage
+        const certificateImage = this.formData.certificateImage
+        if (productImage) {
+          this.fileList1.push({ name: 'productImage', url: productImage })
+        }
+        if (certificateImage) {
+          this.fileList2.push({ name: 'certificateImage', url: certificateImage })
+        }
+      }, 200)
+    },
+    // 保存表单数据
+    save() {
+      this.isLoading = true
+      this.formData.createBy = this.proxyInfo?.authUserId || this.authUserId
+      this.formData.authUserId = this.proxyInfo?.authUserId || this.authUserId
+      saveProduct(this.formData)
+        .then(res => {
+          if (res.code !== 0) return
+          const h = this.$createElement
+          this.$notify.success({
+            title: '修改设备',
+            message: h('i', { style: 'color: #333' }, `已修改设备:"${this.formData.productName}"`),
+            duration: 2000
+          })
+          this.$store.dispatch('tagsView/delView', this.$route)
+          this.$router.back()
+        })
+        .finally(() => {
+          this.isLoading = false
+        })
+    },
+    // 保存参数到formdata
+    setParamToFormData() {
+      return this.paramList.filter(item => item.paramContent !== '' && item.paramName !== '')
+    },
+    // 添加一栏参数
+    handleAddParam() {
+      this.paramsCount += 1
+      this.paramList.push({
+        paramContent: '',
+        paramName: ''
+      })
+    },
+    // 删除一栏参数
+    handleRemoveParam(index) {
+      this.paramsCount -= 1
+      this.paramList.splice(index, 1)
+    },
+    // 图片上传成功 产品图片
+    imageUploadSuccess1(data) {
+      this.formData.productImage = data.data
+    },
+    // 图片上传成功 授权牌照
+    imageUploadSuccess2(data) {
+      this.formData.certificateImage = data.data
+    },
+    setParamList(data) {
+      this.paramList = data.paramList
+    },
+    // 初始化参数列表
+    initParamList(count) {
+      for (let i = 0; i < count; i++) {
+        this.paramList.push({
+          paramContent: '',
+          paramName: ''
+        })
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.addProduct {
+  margin-bottom: 80px;
+  .form-group {
+    margin-bottom: 2%;
+    .param-title {
+      width: 30%;
+    }
+    .param-info {
+      width: 68%;
+      margin-left: 2%;
+    }
+  }
+}
+.addForm {
+  width: 500px;
+  margin: 0 auto;
+  margin-top: 80px;
+}
+.submit-btn {
+  text-align: center;
+  .el-button {
+    width: 140px;
+  }
+}
+.paramsItem {
+  position: relative;
+  .closed {
+    position: absolute;
+    top: 50%;
+    transform: translateY(-50%);
+    right: -20px;
+    cursor: pointer;
+    color: #ddd;
+    &:hover {
+      color: #333;
+    }
+  }
+}
+.hiddenInput {
+  height: 0;
+  display: none;
+}
+</style>

+ 1 - 1
src/views/authentic/supplier/product/index.vue

@@ -100,7 +100,7 @@
       </el-table-column>
       <el-table-column label="操作" align="center" width="240px" class-name="small-padding fixed-width">
         <template slot-scope="{row}">
-          <el-button type="primary" size="mini" @click="handleShowQRcode(row)">查看</el-button>
+          <el-button type="primary" size="mini" @click="$_navigationTo(`auth-product-detail?id=${row.productId}`)">查看</el-button>
           <el-button type="primary" size="mini" :disabled="row.auditStatus !== 1" @click="handleShowQRcode(row)">
             二维码
           </el-button>