瀏覽代碼

新增体疗师二维码

xiebaomin 1 年之前
父節點
當前提交
0b689d8dbd

+ 249 - 0
src/components/QrcodeOperator/index.vue

@@ -0,0 +1,249 @@
+<template>
+  <div class="code-container">
+    <div class="qrcode">
+      <div class="title">{{ operatorInfo.createBy + "官方认证" + `${authUserId == 12 ? '体疗师' : '操作师'}` }}</div>
+      <div class="content">
+        <img :src="imgUrl" alt="">
+      </div>
+      <div class="btn down-btn" @click="handleDown">下载二维码</div>
+      <div class="btn close-btn" @click="handleClose">关闭</div>
+    </div>
+    <canvas id="canvas" style="display: none" />
+    <div v-if="isVisible" class="mask" @click="handleClose" />
+    <a id="downloadLink" href="#" style="display: none" />
+  </div>
+</template>
+
+<script>
+import QRCode from 'qrcode'
+import downImage from '@/assets/img/qrcode-bg-club-down.png'
+import { mapGetters } from 'vuex'
+export default {
+  name: 'QrcodeClub',
+  props: {
+    operatorInfo: {
+      type: Object,
+      default: () => {}
+    },
+    isVisible: {
+      type: Boolean,
+      default: true
+    }
+  },
+  data() {
+    return {
+      imgUrl: '',
+      wwwHost: process.env.VUE_APP_WWW_HOST,
+      qrcodePath: ''
+    }
+  },
+  computed: {
+    ...mapGetters(['authUserId', 'name', 'prefix'])
+  },
+  created() {
+    this.initQrcode()
+  },
+  methods: {
+    // 关闭二维码
+    handleClose() {
+      this.$emit('close')
+    },
+    // 下载二维码
+    handleDown() {
+      this.createDownFile((downCanvas) => {
+        // 构造url
+        var url = downCanvas.toDataURL('image/jpg')
+        // 构造a标签并模拟点击
+        var downloadLink = document.getElementById('downloadLink')
+        downloadLink.setAttribute('href', url)
+        downloadLink.setAttribute('download', '二维码.jpg')
+        downloadLink.click()
+      })
+    },
+    // 初始化二维码
+    async initQrcode() {
+      this.qrcodePath = `${this.wwwHost}/${this.authUserId}/${this.prefix}/approve/personnel/operate/detail?id=${this.operatorInfo.doctorId}`
+      // 二维码配置
+      const options = {
+        width: 192,
+        height: 192,
+        margin: 1
+      }
+      try {
+        this.imgUrl = await QRCode.toDataURL(this.qrcodePath, options)
+      } catch (err) {
+        console.error(err)
+      }
+    },
+    // 生成下载的文件
+    async createDownFile(callback) {
+      this.qrcodePath = `${this.wwwHost}/${this.authUserId}/${this.prefix}/approve/personnel/operate/detail?id=${this.operatorInfo.doctorId}`
+      const strHeader = this.name + '正品授权'
+      const strFooter = this.operatorInfo.doctorName
+      // 生成二维码参数信息
+      const options = {
+        width: 720,
+        height: 720,
+        margin: 1
+      }
+      // 生成二维码dataURL
+      const downDataURL = await QRCode.toDataURL(this.qrcodePath, options)
+
+      // 设置下载二维码
+      const downCanvas = document.getElementById('canvas')
+      const downImg = new Image()
+      const downBgImg = new Image()
+      downImg.src = downDataURL
+      downBgImg.src = downImage
+      downBgImg.onload = function() {
+        // 重新绘制画布
+        const w = this.width
+        const h = this.height
+        downCanvas.width = w
+        downCanvas.height = h
+        const ctx = downCanvas.getContext('2d')
+        // 设置画布背景
+        ctx.fillStyle = '#ffffff'
+        ctx.fillRect(0, 0, downCanvas.width, downCanvas.height)
+        // 设置文字样式
+        ctx.fillStyle = '#ffffff'
+        ctx.font = 'bold 52px MicrosoftYaHei'
+        ctx.textAlign = 'center'
+        // 绘制背景
+        ctx.drawImage(this, 0, 0)
+        // 绘制二维码
+        ctx.drawImage(downImg, 185, 342)
+        // 绘制顶部文字描述
+        const chr1 = strHeader.split('')
+        let temp1 = ''
+        const row1 = []
+        for (let a = 0; a < chr1.length; a++) {
+          if (ctx.measureText(temp1).width >= w - 290) {
+            row1.push(temp1)
+            temp1 = ''
+          }
+          temp1 += chr1[a]
+        }
+        row1.push(temp1)
+        if (row1.length === 1) {
+          ctx.fillText(row1[0], w / 2, 170)
+        } else {
+          for (let b = 0; b < row1.length; b++) {
+            ctx.fillText(row1[b], w / 2, 170 - (row1.length - b - 1) * 65)
+          }
+        }
+
+        const chr2 = strFooter.split('')
+        let temp2 = ''
+        const row2 = []
+        for (let a = 0; a < chr2.length; a++) {
+          if (ctx.measureText(temp2).width >= w - 290) {
+            row2.push(temp2)
+            temp2 = ''
+          }
+          temp2 += chr2[a]
+        }
+        row2.push(temp2)
+        if (row2.length === 1) {
+          ctx.fillText(row2[0], w / 2, 170 + 1040)
+        } else {
+          for (let b = 0; b < row2.length; b++) {
+            ctx.fillText(row2[b], w / 2, 170 + 1070 - (row2.length - b - 1) * 65)
+          }
+        }
+
+        // 绘制完成后的回调
+        callback(downCanvas)
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.code-container {
+  position: relative;
+  z-index: 999999;
+}
+.mask {
+  position: fixed;
+  top: 0;
+  left: 0;
+  z-index: 999998;
+  width: 100vw;
+  height: 100vh;
+  background: rgba(0, 0, 0, 0.5);
+}
+.qrcode {
+  z-index: 999999;
+  position: fixed;
+  left: 50%;
+  top: 20%;
+  transform: translateX(-50%);
+  width: 300px;
+  height: 400px;
+  background: url(../../assets/img/qrcode-bg-club-show.png) no-repeat center;
+  .content {
+    width: 192px;
+    height: 192px;
+    position: absolute;
+    left: 54px;
+    bottom: 85px;
+  }
+  .down-btn {
+    left: 0;
+  }
+  .close-btn {
+    right: 0;
+  }
+  .title {
+    position: absolute;
+    top: 30px;
+    left: 50%;
+    transform: translateX(-50%);
+    width: 256px;
+    text-align: center;
+    font-size: 16px;
+    color: #fff;
+    font-weight: bold;
+  }
+
+  .sub-title {
+    position: absolute;
+    bottom: 20px;
+    left: 50%;
+    transform: translateX(-50%);
+    width: 256px;
+    text-align: center;
+    font-size: 16px;
+    color: #fff;
+    font-weight: bold;
+  }
+  .sncode {
+    position: absolute;
+    top: 78px;
+    left: 50%;
+    transform: translateX(-50%);
+    text-align: center;
+    width: 192px;
+    color: #0e9ef0;
+    font-size: 14px;
+    span {
+      font-weight: bold;
+    }
+  }
+}
+.btn {
+  position: absolute;
+  bottom: -60px;
+  width: 108px;
+  height: 32px;
+  background-image: linear-gradient(-90deg, #50c0ff 0%, #0e90dc 100%);
+  border-radius: 4px;
+  text-align: center;
+  line-height: 32px;
+  color: #fff;
+  font-size: 14px;
+  cursor: pointer;
+}
+</style>

+ 249 - 0
src/components/QrcodeTraniner/index.vue

@@ -0,0 +1,249 @@
+<template>
+  <div class="code-container">
+    <div class="qrcode">
+      <div class="title">{{ operatorInfo.createBy + "官方认证培训师" }}</div>
+      <div class="content">
+        <img :src="imgUrl" alt="">
+      </div>
+      <div class="btn down-btn" @click="handleDown">下载二维码</div>
+      <div class="btn close-btn" @click="handleClose">关闭</div>
+    </div>
+    <canvas id="canvas" style="display: none" />
+    <div v-if="isVisible" class="mask" @click="handleClose" />
+    <a id="downloadLink" href="#" style="display: none" />
+  </div>
+</template>
+
+<script>
+import QRCode from 'qrcode'
+import downImage from '@/assets/img/qrcode-bg-club-down.png'
+import { mapGetters } from 'vuex'
+export default {
+  name: 'QrcodeClub',
+  props: {
+    operatorInfo: {
+      type: Object,
+      default: () => {}
+    },
+    isVisible: {
+      type: Boolean,
+      default: true
+    }
+  },
+  data() {
+    return {
+      imgUrl: '',
+      wwwHost: process.env.VUE_APP_WWW_HOST,
+      qrcodePath: ''
+    }
+  },
+  computed: {
+    ...mapGetters(['authUserId', 'name', 'prefix'])
+  },
+  created() {
+    this.initQrcode()
+  },
+  methods: {
+    // 关闭二维码
+    handleClose() {
+      this.$emit('close')
+    },
+    // 下载二维码
+    handleDown() {
+      this.createDownFile((downCanvas) => {
+        // 构造url
+        var url = downCanvas.toDataURL('image/jpg')
+        // 构造a标签并模拟点击
+        var downloadLink = document.getElementById('downloadLink')
+        downloadLink.setAttribute('href', url)
+        downloadLink.setAttribute('download', '二维码.jpg')
+        downloadLink.click()
+      })
+    },
+    // 初始化二维码
+    async initQrcode() {
+      this.qrcodePath = `${this.wwwHost}/${this.authUserId}/${this.prefix}/approve/personnel/operate/detail?id=${this.operatorInfo.doctorId}`
+      // 二维码配置
+      const options = {
+        width: 192,
+        height: 192,
+        margin: 1
+      }
+      try {
+        this.imgUrl = await QRCode.toDataURL(this.qrcodePath, options)
+      } catch (err) {
+        console.error(err)
+      }
+    },
+    // 生成下载的文件
+    async createDownFile(callback) {
+      this.qrcodePath = `${this.wwwHost}/${this.authUserId}/${this.prefix}/approve/personnel/operate/detail?id=${this.operatorInfo.doctorId}`
+      const strHeader = this.name + '正品授权'
+      const strFooter = this.operatorInfo.doctorName
+      // 生成二维码参数信息
+      const options = {
+        width: 720,
+        height: 720,
+        margin: 1
+      }
+      // 生成二维码dataURL
+      const downDataURL = await QRCode.toDataURL(this.qrcodePath, options)
+
+      // 设置下载二维码
+      const downCanvas = document.getElementById('canvas')
+      const downImg = new Image()
+      const downBgImg = new Image()
+      downImg.src = downDataURL
+      downBgImg.src = downImage
+      downBgImg.onload = function() {
+        // 重新绘制画布
+        const w = this.width
+        const h = this.height
+        downCanvas.width = w
+        downCanvas.height = h
+        const ctx = downCanvas.getContext('2d')
+        // 设置画布背景
+        ctx.fillStyle = '#ffffff'
+        ctx.fillRect(0, 0, downCanvas.width, downCanvas.height)
+        // 设置文字样式
+        ctx.fillStyle = '#ffffff'
+        ctx.font = 'bold 52px MicrosoftYaHei'
+        ctx.textAlign = 'center'
+        // 绘制背景
+        ctx.drawImage(this, 0, 0)
+        // 绘制二维码
+        ctx.drawImage(downImg, 185, 342)
+        // 绘制顶部文字描述
+        const chr1 = strHeader.split('')
+        let temp1 = ''
+        const row1 = []
+        for (let a = 0; a < chr1.length; a++) {
+          if (ctx.measureText(temp1).width >= w - 290) {
+            row1.push(temp1)
+            temp1 = ''
+          }
+          temp1 += chr1[a]
+        }
+        row1.push(temp1)
+        if (row1.length === 1) {
+          ctx.fillText(row1[0], w / 2, 170)
+        } else {
+          for (let b = 0; b < row1.length; b++) {
+            ctx.fillText(row1[b], w / 2, 170 - (row1.length - b - 1) * 65)
+          }
+        }
+
+        const chr2 = strFooter.split('')
+        let temp2 = ''
+        const row2 = []
+        for (let a = 0; a < chr2.length; a++) {
+          if (ctx.measureText(temp2).width >= w - 290) {
+            row2.push(temp2)
+            temp2 = ''
+          }
+          temp2 += chr2[a]
+        }
+        row2.push(temp2)
+        if (row2.length === 1) {
+          ctx.fillText(row2[0], w / 2, 170 + 1040)
+        } else {
+          for (let b = 0; b < row2.length; b++) {
+            ctx.fillText(row2[b], w / 2, 170 + 1070 - (row2.length - b - 1) * 65)
+          }
+        }
+
+        // 绘制完成后的回调
+        callback(downCanvas)
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.code-container {
+  position: relative;
+  z-index: 999999;
+}
+.mask {
+  position: fixed;
+  top: 0;
+  left: 0;
+  z-index: 999998;
+  width: 100vw;
+  height: 100vh;
+  background: rgba(0, 0, 0, 0.5);
+}
+.qrcode {
+  z-index: 999999;
+  position: fixed;
+  left: 50%;
+  top: 20%;
+  transform: translateX(-50%);
+  width: 300px;
+  height: 400px;
+  background: url(../../assets/img/qrcode-bg-club-show.png) no-repeat center;
+  .content {
+    width: 192px;
+    height: 192px;
+    position: absolute;
+    left: 54px;
+    bottom: 85px;
+  }
+  .down-btn {
+    left: 0;
+  }
+  .close-btn {
+    right: 0;
+  }
+  .title {
+    position: absolute;
+    top: 30px;
+    left: 50%;
+    transform: translateX(-50%);
+    width: 256px;
+    text-align: center;
+    font-size: 16px;
+    color: #fff;
+    font-weight: bold;
+  }
+
+  .sub-title {
+    position: absolute;
+    bottom: 20px;
+    left: 50%;
+    transform: translateX(-50%);
+    width: 256px;
+    text-align: center;
+    font-size: 16px;
+    color: #fff;
+    font-weight: bold;
+  }
+  .sncode {
+    position: absolute;
+    top: 78px;
+    left: 50%;
+    transform: translateX(-50%);
+    text-align: center;
+    width: 192px;
+    color: #0e9ef0;
+    font-size: 14px;
+    span {
+      font-weight: bold;
+    }
+  }
+}
+.btn {
+  position: absolute;
+  bottom: -60px;
+  width: 108px;
+  height: 32px;
+  background-image: linear-gradient(-90deg, #50c0ff 0%, #0e90dc 100%);
+  border-radius: 4px;
+  text-align: center;
+  line-height: 32px;
+  color: #fff;
+  font-size: 14px;
+  cursor: pointer;
+}
+</style>

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

@@ -209,6 +209,7 @@ export default {
       try {
         this.formData.certificateImage = this.formData.certificateImageType === 0 ? '' : this.formData.certificateImage
         this.formData.authDate = this.formData.authDate ? formatDate(this.formData.authDate, 'yyyy.MM.DD') : ''
+        console.log('授权牌数据', this.formData)
         await saveProduct(this.formData)
         const h = this.$createElement
         const tip = this.editType === 'add' ? '添加' : '修改'

+ 200 - 183
src/views/normal/personnel/operate/index.vue

@@ -1,183 +1,200 @@
-<template>
-  <div class="app-container">
-    <div class="filter-container">
-      <div class="filter-control">
-        <span>操作师姓名:</span>
-        <el-input v-model="listQuery.doctorName" placeholder="操作师姓名" @keyup.enter.native="handleFilter" />
-      </div>
-      <div class="filter-control">
-        <span>审核状态:</span>
-        <el-select v-model="listQuery.auditStatus" placeholder="审核状态" clearable @change="getList">
-          <el-option label="全部" value="" />
-          <el-option label="待审核" :value="2" />
-          <el-option label="审核通过" :value="1" />
-          <el-option label="审核未通过" :value="0" />
-        </el-select>
-      </div>
-      <div class="filter-control">
-        <span>上线状态:</span>
-        <el-select v-model="listQuery.status" placeholder="上线状态" clearable @change="getList">
-          <el-option label="全部" value="" />
-          <el-option label="已上线" :value="1" />
-          <el-option label="待上线" :value="2" />
-          <el-option label="未上线" :value="0" />
-        </el-select>
-      </div>
-      <div class="filter-control">
-        <permission-button type="primary" @click="getList">查询</permission-button>
-        <permission-button type="primary" @click="navigationTo('add?type=add')">添加</permission-button>
-      </div>
-    </div>
-    <!-- 表格区域 -->
-    <el-table
-      :key="tableKey"
-      :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="120px" align="center">
-        <template slot-scope="{ row }">
-          <audit-status :status="row.auditStatus" :reason="row.invalidReason" />
-        </template>
-      </el-table-column>
-
-      <el-table-column label="上线状态" width="160px" 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>
-              <permission-button type="primary" size="mini" @click="handleChangeStatus(row)">上线</permission-button>
-            </template>
-            <template v-else>
-              <span style="margin-right: 10px" class="status success">已上线</span>
-              <permission-button type="info" size="mini" @click="handleChangeStatus(row)">下线</permission-button>
-            </template>
-          </template>
-          <template v-else-if="row.auditStatus === 2">
-            <!-- <el-tag type="warning">待上线</el-tag> -->
-            <span style="margin-right: 10px" class="status warning">待上线</span>
-          </template>
-          <template v-else>
-            <!-- <el-tag type="warning">待上线</el-tag> -->
-            <span style="margin-right: 10px" class="status danger">已下线</span>
-          </template>
-        </template>
-      </el-table-column>
-      <el-table-column label="创建时间" class-name="status-col" width="160px" align="center">
-        <template slot-scope="{ row }">
-          <span>{{ row.createTime | formatTime }}</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 }">
-          <permission-button type="primary" size="mini" @click="navigationTo(`edit?type=edit&id=${row.doctorId}`)">
-            编辑
-          </permission-button>
-          <permission-button type="danger" size="mini" @click="handleRemoveDoctor(row)"> 删除 </permission-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <!-- 页码 -->
-    <pagination :total="total" :page.sync="listQuery.pageNum" :limit.sync="listQuery.pageSize" @pagination="getList" />
-  </div>
-</template>
-
-<script>
-import { mapGetters } from 'vuex'
-import { fetchDoctorList, removeDoctor, doctorStatusChange } from '@/api/doctor'
-
-export default {
-  name: 'OperateDoctorList',
-  data() {
-    return {
-      tableKey: 0,
-      total: 0,
-      listQuery: {
-        authUserId: '',
-        auditStatus: '',
-        certificateNo: '',
-        doctorName: '',
-        doctorType: 1,
-        listType: 1,
-        status: '',
-        pageNum: 1,
-        pageSize: 10
-      },
-      list: []
-    }
-  },
-  computed: {
-    ...mapGetters(['authUserId'])
-  },
-  created() {
-    this.getList()
-  },
-  activated() {
-    this.getList()
-  },
-  methods: {
-    // 获取列表
-    getList() {
-      this.listQuery.authUserId = this.authUserId
-      fetchDoctorList(this.listQuery)
-        .then((res) => {
-          console.log(res)
-          this.list = res.data.list
-          this.total = res.data.total
-        })
-        .catch((error) => {
-          console.log(error)
-        })
-    },
-    // 修改状态
-    handleChangeStatus(row) {
-      const status = row.status === 1 ? 0 : 1
-
-      doctorStatusChange({ doctorId: row.doctorId, status })
-        .then((res) => {
-          this.$message.success('状态修改成功')
-          this.getList()
-        })
-        .catch((error) => {
-          console.log(error)
-        })
-    },
-    // 删除
-    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()
-        })
-        .catch((error) => {
-          console.log(error)
-        })
-    },
-    // 表格索引
-    indexMethod(index) {
-      return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped></style>
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <div class="filter-control">
+        <span>操作师姓名:</span>
+        <el-input v-model="listQuery.doctorName" placeholder="操作师姓名" @keyup.enter.native="handleFilter" />
+      </div>
+      <div class="filter-control">
+        <span>审核状态:</span>
+        <el-select v-model="listQuery.auditStatus" placeholder="审核状态" clearable @change="getList">
+          <el-option label="全部" value="" />
+          <el-option label="待审核" :value="2" />
+          <el-option label="审核通过" :value="1" />
+          <el-option label="审核未通过" :value="0" />
+        </el-select>
+      </div>
+      <div class="filter-control">
+        <span>上线状态:</span>
+        <el-select v-model="listQuery.status" placeholder="上线状态" clearable @change="getList">
+          <el-option label="全部" value="" />
+          <el-option label="已上线" :value="1" />
+          <el-option label="待上线" :value="2" />
+          <el-option label="未上线" :value="0" />
+        </el-select>
+      </div>
+      <div class="filter-control">
+        <permission-button type="primary" @click="getList">查询</permission-button>
+        <permission-button type="primary" @click="navigationTo('add?type=add')">添加</permission-button>
+      </div>
+    </div>
+    <!-- 表格区域 -->
+    <el-table
+      :key="tableKey"
+      :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="120px" align="center">
+        <template slot-scope="{ row }">
+          <audit-status :status="row.auditStatus" :reason="row.invalidReason" />
+        </template>
+      </el-table-column>
+
+      <el-table-column label="上线状态" width="160px" 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>
+              <permission-button type="primary" size="mini" @click="handleChangeStatus(row)">上线</permission-button>
+            </template>
+            <template v-else>
+              <span style="margin-right: 10px" class="status success">已上线</span>
+              <permission-button type="info" size="mini" @click="handleChangeStatus(row)">下线</permission-button>
+            </template>
+          </template>
+          <template v-else-if="row.auditStatus === 2">
+            <!-- <el-tag type="warning">待上线</el-tag> -->
+            <span style="margin-right: 10px" class="status warning">待上线</span>
+          </template>
+          <template v-else>
+            <!-- <el-tag type="warning">待上线</el-tag> -->
+            <span style="margin-right: 10px" class="status danger">已下线</span>
+          </template>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建时间" class-name="status-col" width="160px" align="center">
+        <template slot-scope="{ row }">
+          <span>{{ row.createTime | formatTime }}</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 }">
+          <permission-button type="primary" size="mini" @click="navigationTo(`edit?type=edit&id=${row.doctorId}`)">
+            编辑
+          </permission-button>
+          <permission-button type="danger" size="mini" @click="handleRemoveDoctor(row)"> 删除 </permission-button>
+          <el-button type="primary" size="mini" @click="handleShowQRcode(row)">
+            二维码
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 页码 -->
+    <pagination :total="total" :page.sync="listQuery.pageNum" :limit.sync="listQuery.pageSize" @pagination="getList" />
+    <!-- 二维码 -->
+    <transition name="fade">
+      <qrcode-operator v-if="showQRcode" :operator-info="operatorInfo" @close="showQRcode = false" />
+    </transition>
+  </div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+import { fetchDoctorList, removeDoctor, doctorStatusChange } from '@/api/doctor'
+import QrcodeOperator from '@/components/QrcodeOperator'
+export default {
+  name: 'OperateDoctorList',
+  components: {
+    QrcodeOperator
+  },
+  data() {
+    return {
+      tableKey: 0,
+      total: 0,
+      listQuery: {
+        authUserId: '',
+        auditStatus: '',
+        certificateNo: '',
+        doctorName: '',
+        doctorType: 1,
+        listType: 1,
+        status: '',
+        pageNum: 1,
+        pageSize: 10
+      },
+      list: [],
+      showQRcode: false, // 二维码
+      operatorInfo: {} // 人员信息
+    }
+  },
+  computed: {
+    ...mapGetters(['authUserId'])
+  },
+  created() {
+    this.getList()
+  },
+  activated() {
+    this.getList()
+  },
+  methods: {
+    // 获取列表
+    getList() {
+      this.listQuery.authUserId = this.authUserId
+      fetchDoctorList(this.listQuery)
+        .then((res) => {
+          console.log(res)
+          this.list = res.data.list
+          this.total = res.data.total
+        })
+        .catch((error) => {
+          console.log(error)
+        })
+    },
+    // 修改状态
+    handleChangeStatus(row) {
+      const status = row.status === 1 ? 0 : 1
+
+      doctorStatusChange({ doctorId: row.doctorId, status })
+        .then((res) => {
+          this.$message.success('状态修改成功')
+          this.getList()
+        })
+        .catch((error) => {
+          console.log(error)
+        })
+    },
+    // 删除
+    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()
+        })
+        .catch((error) => {
+          console.log(error)
+        })
+    },
+    // 表格索引
+    indexMethod(index) {
+      return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1
+    },
+    // 二维码
+    handleShowQRcode(row) {
+      this.operatorInfo = row
+      this.showQRcode = true
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped></style>

+ 200 - 183
src/views/normal/personnel/training/index.vue

@@ -1,183 +1,200 @@
-<template>
-  <div class="app-container">
-    <div class="filter-container">
-      <div class="filter-control">
-        <span>培训师姓名:</span>
-        <el-input v-model="listQuery.doctorName" placeholder="培训师姓名" @keyup.enter.native="handleFilter" />
-      </div>
-      <div class="filter-control">
-        <span>审核状态:</span>
-        <el-select v-model="listQuery.auditStatus" placeholder="审核状态" clearable @change="getList">
-          <el-option label="全部" value="" />
-          <el-option label="待审核" :value="2" />
-          <el-option label="审核通过" :value="1" />
-          <el-option label="审核未通过" :value="0" />
-        </el-select>
-      </div>
-      <div class="filter-control">
-        <span>上线状态:</span>
-        <el-select v-model="listQuery.status" placeholder="上线状态" clearable @change="getList">
-          <el-option label="全部" value="" />
-          <el-option label="已上线" :value="1" />
-          <el-option label="待上线" :value="2" />
-          <el-option label="未上线" :value="0" />
-        </el-select>
-      </div>
-      <div class="filter-control">
-        <permission-button type="primary" @click="getList">查询</permission-button>
-        <permission-button type="primary" @click="navigationTo('add?type=add')">添加</permission-button>
-      </div>
-    </div>
-    <!-- 表格区域 -->
-    <el-table
-      :key="tableKey"
-      :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="120px" align="center">
-        <template slot-scope="{ row }">
-          <audit-status :status="row.auditStatus" :reason="row.invalidReason" />
-        </template>
-      </el-table-column>
-
-      <el-table-column label="上线状态" width="160px" 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>
-              <permission-button type="primary" size="mini" @click="handleChangeStatus(row)">上线</permission-button>
-            </template>
-            <template v-else>
-              <span style="margin-right: 10px" class="status success">已上线</span>
-              <permission-button type="info" size="mini" @click="handleChangeStatus(row)">下线</permission-button>
-            </template>
-          </template>
-          <template v-else-if="row.auditStatus === 2">
-            <!-- <el-tag type="warning">待上线</el-tag> -->
-            <span style="margin-right: 10px" class="status warning">待上线</span>
-          </template>
-          <template v-else>
-            <!-- <el-tag type="warning">待上线</el-tag> -->
-            <span style="margin-right: 10px" class="status danger">已下线</span>
-          </template>
-        </template>
-      </el-table-column>
-      <el-table-column label="创建时间" class-name="status-col" width="160px" align="center">
-        <template slot-scope="{ row }">
-          <span>{{ row.createTime | formatTime }}</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 }">
-          <permission-button type="primary" size="mini" @click="navigationTo(`edit?type=edit&id=${row.doctorId}`)">
-            编辑
-          </permission-button>
-          <permission-button type="danger" size="mini" @click="handleRemoveDoctor(row)"> 删除 </permission-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <!-- 页码 -->
-    <pagination :total="total" :page.sync="listQuery.pageNum" :limit.sync="listQuery.pageSize" @pagination="getList" />
-  </div>
-</template>
-
-<script>
-import { mapGetters } from 'vuex'
-import { fetchDoctorList, removeDoctor, doctorStatusChange } from '@/api/doctor'
-
-export default {
-  name: 'TrainingDoctorList',
-  data() {
-    return {
-      tableKey: 0,
-      total: 0,
-      listQuery: {
-        authUserId: '',
-        auditStatus: '',
-        certificateNo: '',
-        doctorName: '',
-        doctorType: 2,
-        listType: 1,
-        status: '',
-        pageNum: 1,
-        pageSize: 10
-      },
-      list: []
-    }
-  },
-  computed: {
-    ...mapGetters(['authUserId'])
-  },
-  created() {
-    this.getList()
-  },
-  activated() {
-    this.getList()
-  },
-  methods: {
-    // 获取列表
-    getList() {
-      this.listQuery.authUserId = this.authUserId
-      fetchDoctorList(this.listQuery)
-        .then((res) => {
-          console.log(res)
-          this.list = res.data.list
-          this.total = res.data.total
-        })
-        .catch((error) => {
-          console.log(error)
-        })
-    },
-    // 修改状态
-    handleChangeStatus(row) {
-      const status = row.status === 1 ? 0 : 1
-
-      doctorStatusChange({ doctorId: row.doctorId, status })
-        .then((res) => {
-          this.$message.success('状态修改成功')
-          this.getList()
-        })
-        .catch((error) => {
-          console.log(error)
-        })
-    },
-    // 删除
-    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()
-        })
-        .catch((error) => {
-          console.log(error)
-        })
-    },
-    // 表格索引
-    indexMethod(index) {
-      return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped></style>
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <div class="filter-control">
+        <span>培训师姓名:</span>
+        <el-input v-model="listQuery.doctorName" placeholder="培训师姓名" @keyup.enter.native="handleFilter" />
+      </div>
+      <div class="filter-control">
+        <span>审核状态:</span>
+        <el-select v-model="listQuery.auditStatus" placeholder="审核状态" clearable @change="getList">
+          <el-option label="全部" value="" />
+          <el-option label="待审核" :value="2" />
+          <el-option label="审核通过" :value="1" />
+          <el-option label="审核未通过" :value="0" />
+        </el-select>
+      </div>
+      <div class="filter-control">
+        <span>上线状态:</span>
+        <el-select v-model="listQuery.status" placeholder="上线状态" clearable @change="getList">
+          <el-option label="全部" value="" />
+          <el-option label="已上线" :value="1" />
+          <el-option label="待上线" :value="2" />
+          <el-option label="未上线" :value="0" />
+        </el-select>
+      </div>
+      <div class="filter-control">
+        <permission-button type="primary" @click="getList">查询</permission-button>
+        <permission-button type="primary" @click="navigationTo('add?type=add')">添加</permission-button>
+      </div>
+    </div>
+    <!-- 表格区域 -->
+    <el-table
+      :key="tableKey"
+      :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="120px" align="center">
+        <template slot-scope="{ row }">
+          <audit-status :status="row.auditStatus" :reason="row.invalidReason" />
+        </template>
+      </el-table-column>
+
+      <el-table-column label="上线状态" width="160px" 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>
+              <permission-button type="primary" size="mini" @click="handleChangeStatus(row)">上线</permission-button>
+            </template>
+            <template v-else>
+              <span style="margin-right: 10px" class="status success">已上线</span>
+              <permission-button type="info" size="mini" @click="handleChangeStatus(row)">下线</permission-button>
+            </template>
+          </template>
+          <template v-else-if="row.auditStatus === 2">
+            <!-- <el-tag type="warning">待上线</el-tag> -->
+            <span style="margin-right: 10px" class="status warning">待上线</span>
+          </template>
+          <template v-else>
+            <!-- <el-tag type="warning">待上线</el-tag> -->
+            <span style="margin-right: 10px" class="status danger">已下线</span>
+          </template>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建时间" class-name="status-col" width="160px" align="center">
+        <template slot-scope="{ row }">
+          <span>{{ row.createTime | formatTime }}</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 }">
+          <permission-button type="primary" size="mini" @click="navigationTo(`edit?type=edit&id=${row.doctorId}`)">
+            编辑
+          </permission-button>
+          <permission-button type="danger" size="mini" @click="handleRemoveDoctor(row)"> 删除 </permission-button>
+          <el-button type="primary" size="mini" @click="handleShowQRcode(row)">
+            二维码
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 二维码 -->
+    <transition name="fade">
+      <qrcode-trainer v-if="showQRcode" :operator-info="operatorInfo" @close="showQRcode = false" />
+    </transition>
+    <!-- 页码 -->
+    <pagination :total="total" :page.sync="listQuery.pageNum" :limit.sync="listQuery.pageSize" @pagination="getList" />
+  </div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+import { fetchDoctorList, removeDoctor, doctorStatusChange } from '@/api/doctor'
+import QrcodeTrainer from '@/components/QrcodeTraniner'
+export default {
+  name: 'TrainingDoctorList',
+  components: {
+    QrcodeTrainer
+  },
+  data() {
+    return {
+      tableKey: 0,
+      total: 0,
+      listQuery: {
+        authUserId: '',
+        auditStatus: '',
+        certificateNo: '',
+        doctorName: '',
+        doctorType: 2,
+        listType: 1,
+        status: '',
+        pageNum: 1,
+        pageSize: 10
+      },
+      list: [],
+      showQRcode: false, // 二维码
+      operatorInfo: {} // 人员信息
+    }
+  },
+  computed: {
+    ...mapGetters(['authUserId'])
+  },
+  created() {
+    this.getList()
+  },
+  activated() {
+    this.getList()
+  },
+  methods: {
+    // 获取列表
+    getList() {
+      this.listQuery.authUserId = this.authUserId
+      fetchDoctorList(this.listQuery)
+        .then((res) => {
+          console.log(res)
+          this.list = res.data.list
+          this.total = res.data.total
+        })
+        .catch((error) => {
+          console.log(error)
+        })
+    },
+    // 修改状态
+    handleChangeStatus(row) {
+      const status = row.status === 1 ? 0 : 1
+
+      doctorStatusChange({ doctorId: row.doctorId, status })
+        .then((res) => {
+          this.$message.success('状态修改成功')
+          this.getList()
+        })
+        .catch((error) => {
+          console.log(error)
+        })
+    },
+    // 删除
+    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()
+        })
+        .catch((error) => {
+          console.log(error)
+        })
+    },
+    // 表格索引
+    indexMethod(index) {
+      return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1
+    },
+    // 二维码
+    handleShowQRcode(row) {
+      this.operatorInfo = row
+      this.showQRcode = true
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped></style>