Pārlūkot izejas kodu

v1.7版本页面接口调试

yuwenjun1997 2 gadi atpakaļ
vecāks
revīzija
1dc2fbdc93

+ 6 - 5
.env.development

@@ -4,12 +4,12 @@ NODE_ENV = development
 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'
@@ -22,8 +22,9 @@ VUE_APP_SOCKET_SERVER = 'wss://zplma-b.caimei365.com/websocket?sessionSource=zpl
 # VUE_APP_LOCAL = 'http://192.168.2.81:9527'
 VUE_APP_LOCAL = 'http://zplm-b.caimei365.com'
 
+# 认证通页面
+VUE_APP_WWW_HOST = 'http://192.168.2.92:8888'
 
 # 支付
 VUE_APP_PAY_LOCAL = 'http://192.168.2.68:18014'
 # VUE_APP_PAY_LOCAL = 'http://zplm-b.caimei365.com
-

+ 10 - 0
src/api/auth.js

@@ -162,3 +162,13 @@ export function unbindGenerate(data) {
     data
   })
 }
+
+// 重置密码
+export function resetClubUserPassword(data) {
+  return request({
+    url: '/club/user/reset/password',
+    method: 'post',
+    data
+  })
+}
+

+ 28 - 0
src/api/logistics.js

@@ -0,0 +1,28 @@
+import request from '@/utils/request'
+
+// 物流公司列表
+export function fetchCompanyList(params) {
+  return request({
+    url: '/logistics/company/data',
+    method: 'get',
+    params
+  })
+}
+
+// 绑定订单(确认寄售)
+export function logisticsSend(data) {
+  return request({
+    url: '/logistics/certificate/send',
+    method: 'post',
+    data
+  })
+}
+
+// 获取物流详情
+export function logisticsDetails(params) {
+  return request({
+    url: '/logistics/certificate/details',
+    method: 'get',
+    params
+  })
+}

BIN
src/assets/img/qrcode-bg-club-down.png


BIN
src/assets/img/qrcode-bg-club-show.png


+ 218 - 0
src/components/qrcode/club-qrcode.vue

@@ -0,0 +1,218 @@
+<template>
+  <div class="code-container">
+    <div class="qrcode">
+      <div class="title">{{ qrcodeData.authParty }}正品授权</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: 'Qrcode',
+  filters: {},
+  props: {
+    qrcodeData: {
+      type: Object,
+      default: () => {}
+    },
+    isVisible: {
+      type: Boolean,
+      default: true
+    }
+  },
+  data() {
+    return {
+      imgUrl: '',
+      wwwServer: process.env.VUE_APP_WWW_HOST,
+      qrcodePath: ''
+    }
+  },
+  computed: {
+    ...mapGetters(['authUserId'])
+  },
+  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() {
+      console.log(this.qrcodeData)
+      this.qrcodePath = `${this.wwwServer}/${this.authUserId}/app/approve/club/detail?id=${this.qrcodeData.authId}`
+      // 二维码配置
+      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.wwwServer}/${this.authUserId}/app/approve/club/detail?id=${this.qrcodeData.authId}`
+      const strHeader = this.qrcodeData.authParty + '正品授权'
+      // 生成二维码参数信息
+      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 chr = strHeader.split('')
+        let temp = ''
+        const row = []
+        for (let a = 0; a < chr.length; a++) {
+          if (ctx.measureText(temp).width >= w - 290) {
+            row.push(temp)
+            temp = ''
+          }
+          temp += chr[a]
+        }
+        row.push(temp)
+        if (row.length === 1) {
+          ctx.fillText(row[0], w / 2, 170)
+        } else {
+          for (var b = 0; b < row.length; b++) {
+            ctx.fillText(row[b], w / 2, 170 - (row.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: 66px;
+  }
+  .down-btn {
+    left: 0;
+  }
+  .close-btn {
+    right: 0;
+  }
+  .title {
+    position: absolute;
+    top: 48px;
+    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>

+ 6 - 0
src/router/module/admin/logistics.js

@@ -39,6 +39,12 @@ const logisticsRoutes = [
         component: () => import('@/views/admin/logistics-licensed/club/device/detail'),
         name: 'LicensedDeviceDetail',
         meta: { title: '设备详情', noCache: true }
+      },
+      {
+        path: 'licensed-record',
+        component: () => import('@/views/admin/logistics-licensed/licensed-record'),
+        name: 'LicensedRecord',
+        meta: { title: '寄送记录', noCache: true }
       }
     ]
   }

+ 2 - 8
src/views/admin/audit/club/device/review.vue

@@ -29,7 +29,7 @@
 
       <div class="row">
         <div class="col">购买渠道:</div>
-        <div class="col">{{ productInfo.buyChannel }}</div>
+        <div class="col">{{ productInfo.purchaseWay }}</div>
       </div>
 
       <div class="row">
@@ -42,7 +42,6 @@
           />
         </div>
       </div>
-
       <div class="row">
         <div class="col">设备参数:</div>
         <div class="col">
@@ -54,11 +53,6 @@
           </template>
         </div>
       </div>
-
-      <div class="row">
-        <div class="col">审核状态:</div>
-        <div class="col">待审核</div>
-      </div>
       <el-form ref="auditForm" label-width="112px" :model="auditForm" :rules="rules">
         <el-form-item label="审核:">
           <el-radio-group v-model="auditForm.auditStatus">
@@ -93,7 +87,7 @@ export default {
         paramList: [],
         invoiceImage: '',
         brandName: '',
-        buyChannel: ''
+        purchaseWay: ''
       },
       auditForm: {
         auditBy: '', // 审核人id

+ 5 - 5
src/views/admin/audit/club/list.vue

@@ -51,7 +51,7 @@
             <el-popover placement="top-start" title="审核说明" width="400" trigger="hover" :content="row.invalidReason">
               <el-tag slot="reference" size="small" type="danger" class="reason">
                 <span>审核未通过</span>
-                <span class="el-icon-question status danger " />
+                <span class="el-icon-question status danger" />
               </el-tag>
             </el-popover>
             <!-- 未通过原因展示END -->
@@ -85,7 +85,7 @@
             v-if="row.auditStatus !== 1"
             type="warning"
             size="mini"
-            style="margin-right:5px"
+            style="margin-right: 5px"
             icon="el-icon-s-check"
             @click="$_navigationTo(`/audit/club/club-detail?authId=${row.authId}`)"
           >审核</el-button>
@@ -198,7 +198,7 @@ export default {
     getList() {
       this.listLoading = true
       fecthAuthList(this.listQuery)
-        .then(response => {
+        .then((response) => {
           if (response.code !== 0) return
           const { list, total } = response.data
           this.list = list
@@ -210,13 +210,13 @@ export default {
     },
     // 审核
     auditStatusHandle() {
-      this.$refs.formRef.validate(valid => {
+      this.$refs.formRef.validate((valid) => {
         if (valid) {
           // 指定审核人
           this.dialogData.auditBy = this.authUserId
           // 提交审核信息
           auditAuth(this.dialogData)
-            .then(res => {
+            .then((res) => {
               if (res.code !== 0) return
               this.$message.success(res.data)
               this.setMessageState({ id: this.dialogData.authId, type: 1 })

+ 35 - 19
src/views/admin/audit/club/review.vue

@@ -50,42 +50,58 @@
       <div class="row">
         <div class="col">机构类型:</div>
         <div class="col">
-          <el-radio-group v-model="clubInfo.clubType">
+          <el-radio-group v-model="clubInfo.firstClubType">
             <el-radio
               v-for="item in clubTypeList"
               :key="item.id"
               :label="item.id"
-              :disabled="clubInfo.clubType !== item.id"
+              :disabled="clubInfo.firstClubType !== item.id"
             >{{ item.name }}</el-radio>
           </el-radio-group>
         </div>
       </div>
-      <div class="row">
+
+      <div v-if="clubInfo.firstClubType === 1" class="row">
         <div class="col">医美类型:</div>
         <div class="col">
-          <el-radio-group v-model="clubInfo.medicalType">
+          <el-radio-group v-model="clubInfo.secondClubType">
+            <el-radio
+              v-for="item in medicalTypeList1"
+              :key="item.id"
+              :label="item.id"
+              :disabled="clubInfo.secondClubType !== item.id"
+            >{{ item.name }}</el-radio>
+          </el-radio-group>
+        </div>
+      </div>
+
+      <div v-if="clubInfo.firstClubType === 2" class="row">
+        <div class="col">生美类型:</div>
+        <div class="col">
+          <el-radio-group v-model="clubInfo.secondClubType">
             <el-radio
-              v-for="item in medicalTypeList"
+              v-for="item in medicalTypeList2"
               :key="item.id"
               :label="item.id"
-              :disabled="clubInfo.clubType !== item.id"
+              :disabled="clubInfo.secondClubType !== item.id"
             >{{ item.name }}</el-radio>
           </el-radio-group>
         </div>
       </div>
+
       <div class="row">
         <div class="col">医疗许可证:</div>
         <div class="col">
           <el-image
             style="width: 120px; height: 120px"
-            :src="clubInfo.licenseImage"
-            :preview-src-list="[clubInfo.licenseImage]"
+            :src="clubInfo.medicalLicenseImage"
+            :preview-src-list="[clubInfo.medicalLicenseImage]"
           />
         </div>
       </div>
       <div class="row">
         <div class="col">员工人数:</div>
-        <div class="col">{{ clubInfo.memberCount }}人</div>
+        <div class="col">{{ clubInfo.empNum }}人</div>
       </div>
 
       <div class="row">
@@ -101,11 +117,6 @@
         <div class="col">店铺备注:</div>
         <div class="col">{{ clubInfo.remarks }}人</div>
       </div>
-
-      <div class="row">
-        <div class="col">审核状态:</div>
-        <div class="col">待审核</div>
-      </div>
       <el-form ref="auditForm" label-width="112px" :model="auditForm" :rules="rules">
         <el-form-item label="审核:">
           <el-radio-group v-model="auditForm.auditStatus">
@@ -150,18 +161,23 @@ export default {
         { id: 4, name: '个人' },
         { id: 5, name: '其他' }
       ],
-      medicalTypeList: [
+      medicalTypeList1: [
         { id: 1, name: '诊所' },
         { id: 2, name: '门诊' },
         { id: 3, name: '医院' },
         { id: 4, name: '其他' }
       ],
+      medicalTypeList2: [
+        { id: 5, name: '美容院' },
+        { id: 6, name: '养生馆' },
+        { id: 7, name: '其他' }
+      ],
       authId: '',
       clubInfo: {
-        medicalType: 1,
-        clubType: 1,
-        licenseImage: '',
-        memberCount: '',
+        secondClubType: 1,
+        firstClubType: 1,
+        medicalLicenseImage: '',
+        empNum: '',
         address: '',
         area: '',
         authId: '',

+ 72 - 32
src/views/admin/logistics-licensed/club/detail.vue

@@ -31,61 +31,78 @@
       <div class="row">
         <div class="col">logo:</div>
         <div class="col">
-          <el-image style="width: 120px; height: 120px" :src="clubInfo.logo" :preview-src-list="[clubInfo.logo]" />
+          <el-image v-if="clubInfo.logo" style="width: 120px; height: 120px" :src="clubInfo.logo" :preview-src-list="[clubInfo.logo]" />
         </div>
       </div>
       <div class="row">
         <div class="col">门头照:</div>
         <div class="col">
-          <template v-for="(image, index) in clubInfo.bannerList">
-            <el-image
-              :key="index"
-              style="width: 120px; height: 120px"
-              :src="image"
-              :preview-src-list="clubInfo.bannerList"
-            />
+          <template v-if="clubInfo.bannerList.length > 0">
+            <template v-for="(image, index) in clubInfo.bannerList">
+              <el-image
+                :key="index"
+                style="width: 120px; height: 120px"
+                :src="image"
+                :preview-src-list="clubInfo.bannerList"
+              />
+            </template>
           </template>
         </div>
       </div>
       <div class="row">
         <div class="col">机构类型:</div>
         <div class="col">
-          <el-radio-group v-model="clubInfo.clubType">
+          <el-radio-group v-model="clubInfo.firstClubType">
             <el-radio
               v-for="item in clubTypeList"
               :key="item.id"
               :label="item.id"
-              :disabled="clubInfo.clubType !== item.id"
+              :disabled="clubInfo.firstClubType !== item.id"
             >{{ item.name }}</el-radio>
           </el-radio-group>
         </div>
       </div>
-      <div class="row">
+      <div v-if="clubInfo.firstClubType === 1" class="row">
         <div class="col">医美类型:</div>
         <div class="col">
-          <el-radio-group v-model="clubInfo.medicalType">
+          <el-radio-group v-model="clubInfo.secondClubType">
             <el-radio
-              v-for="item in medicalTypeList"
+              v-for="item in medicalTypeList1"
               :key="item.id"
               :label="item.id"
-              :disabled="clubInfo.clubType !== item.id"
+              :disabled="clubInfo.firstClubType !== item.id"
             >{{ item.name }}</el-radio>
           </el-radio-group>
         </div>
       </div>
+
+      <div v-if="clubInfo.firstClubType === 2" class="row">
+        <div class="col">生美类型:</div>
+        <div class="col">
+          <el-radio-group v-model="clubInfo.secondClubType">
+            <el-radio
+              v-for="item in medicalTypeList2"
+              :key="item.id"
+              :label="item.id"
+              :disabled="clubInfo.firstClubType !== item.id"
+            >{{ item.name }}</el-radio>
+          </el-radio-group>
+        </div>
+      </div>
+
       <div class="row">
         <div class="col">医疗许可证:</div>
         <div class="col">
           <el-image
             style="width: 120px; height: 120px"
-            :src="clubInfo.licenseImage"
-            :preview-src-list="[clubInfo.licenseImage]"
+            :src="clubInfo.medicalLicenseImage"
+            :preview-src-list="[clubInfo.medicalLicenseImage]"
           />
         </div>
       </div>
       <div class="row">
         <div class="col">员工人数:</div>
-        <div class="col">{{ clubInfo.memberCount }}人</div>
+        <div class="col">{{ clubInfo.empNum }}人</div>
       </div>
 
       <div class="row">
@@ -101,6 +118,15 @@
         <div class="col">店铺备注:</div>
         <div class="col">{{ clubInfo.remarks }}人</div>
       </div>
+
+      <!-- <div class="row">
+        <div class="col">审核状态:</div>
+        <div class="col">
+          <span v-if="clubInfo.auditStatus === 2" class="status warning">待审核</span>
+          <span v-else-if="clubInfo.auditStatus === 1" class="status success">审核通过</span>
+          <span v-else class="status danger">审核未通过</span>
+        </div>
+      </div> -->
     </div>
 
     <!-- 地图坐标拾取 -->
@@ -113,12 +139,14 @@
 
 <script>
 import AMapUI from '@/components/AMapUI'
+import { getAuthFormData } from '@/api/auth'
 export default {
   components: {
     [AMapUI.name]: AMapUI
   },
   data() {
     return {
+      authId: '',
       dialogMapVisible: false,
       clubTypeList: [
         { id: 1, name: '医美' },
@@ -127,29 +155,31 @@ export default {
         { id: 4, name: '个人' },
         { id: 5, name: '其他' }
       ],
-      medicalTypeList: [
+      medicalTypeList1: [
         { id: 1, name: '诊所' },
         { id: 2, name: '门诊' },
         { id: 3, name: '医院' },
         { id: 4, name: '其他' }
       ],
+      medicalTypeList2: [
+        { id: 5, name: '美容院' },
+        { id: 6, name: '养生馆' },
+        { id: 7, name: '其他' }
+      ],
       clubInfo: {
-        medicalType: 1,
-        clubType: 1,
-        licenseImage: 'https://fuss10.elemecdn.com/8/27/f01c15bb73e1ef3793e64e6b7bbccjpeg.jpeg',
-        memberCount: 10,
-        address: '广东省深圳市龙华区大浪街道',
-        area: '广东省深圳市龙华区',
+        secondClubType: 1,
+        firstClubType: 1,
+        medicalLicenseImage: '',
+        empNum: 10,
+        address: '',
+        area: '',
         authId: '',
-        authParty: '水柔医美',
-        bannerList: [
-          'https://fuss10.elemecdn.com/8/27/f01c15bb73e1ef3793e64e6b7bbccjpeg.jpeg',
-          'https://fuss10.elemecdn.com/1/8e/aeffeb4de74e2fde4bd74fc7b4486jpeg.jpeg'
-        ],
+        authParty: '',
+        bannerList: [],
         cityId: '',
-        lngAndLat: '116.42729,39.904993',
-        logo: 'https://fuss10.elemecdn.com/8/27/f01c15bb73e1ef3793e64e6b7bbccjpeg.jpeg',
-        mobile: '15872950940',
+        lngAndLat: '',
+        logo: '',
+        mobile: '',
         provinceId: '',
         townId: '',
         customFlag: 0,
@@ -157,7 +187,17 @@ export default {
       }
     }
   },
+  created() {
+    this.authId = this.$route.query.id
+    this.getDetail()
+  },
   methods: {
+    // 数据回显
+    getDetail() {
+      getAuthFormData({ authId: this.authId }).then((res) => {
+        this.clubInfo = { ...this.clubInfo, ...res.data }
+      })
+    }
   }
 }
 </script>

+ 37 - 19
src/views/admin/logistics-licensed/club/device/detail.vue

@@ -29,7 +29,7 @@
 
       <div class="row">
         <div class="col">购买渠道:</div>
-        <div class="col">{{ productInfo.buyChannel }}</div>
+        <div class="col">{{ productInfo.purchaseWay }}</div>
       </div>
 
       <div class="row">
@@ -54,36 +54,54 @@
           </template>
         </div>
       </div>
+
+      <!-- <div class="row">
+        <div class="col">审核状态:</div>
+        <div class="col">
+          <span v-if="productInfo.auditStatus === 2" class="status warning">待审核</span>
+          <span v-else-if="productInfo.auditStatus === 1" class="status success">审核通过</span>
+          <span v-else class="status danger">审核未通过</span>
+        </div>
+      </div> -->
     </div>
   </div>
 </template>
 
 <script>
+import { getProductById } from '@/api/product'
 export default {
   data() {
     return {
+      isLoading: true,
+      productId: '',
       productInfo: {
-        productName: '产品名称产品名称',
-        snCode: 'adsgfadsgdsagasg',
-        productImage: 'https://fuss10.elemecdn.com/8/27/f01c15bb73e1ef3793e64e6b7bbccjpeg.jpeg',
-        certificateImage: 'https://fuss10.elemecdn.com/8/27/f01c15bb73e1ef3793e64e6b7bbccjpeg.jpeg',
-        paramList: [{
-          paramName: '参数名称',
-          paramContent: '参数信息信息'
-        }, {
-          paramName: '参数名称',
-          paramContent: '参数信息信息'
-        }, {
-          paramName: '参数名称',
-          paramContent: '参数信息信息'
-        }],
-        invoiceImage: 'https://fuss10.elemecdn.com/8/27/f01c15bb73e1ef3793e64e6b7bbccjpeg.jpeg',
-        brandName: '品牌名',
-        buyChannel: '购买渠道'
+        productName: '',
+        snCode: '',
+        productImage: '',
+        certificateImage: '',
+        paramList: [],
+        invoiceImage: '',
+        brandName: '',
+        purchaseWay: ''
       }
     }
   },
+  created() {
+    this.productId = this.$route.query.id
+    this.getDetail()
+  },
   methods: {
+    // 获取商品详情
+    getDetail() {
+      this.isLoading = true
+      getProductById({ productId: this.productId })
+        .then((res) => {
+          this.productInfo = { ...this.productInfo, ...res.data }
+        })
+        .finally(() => {
+          this.isLoading = false
+        })
+    }
   }
 }
 </script>
@@ -109,7 +127,7 @@ export default {
       padding-bottom: 16px;
       text-align: left;
 
-      &:first-child{
+      &:first-child {
         text-align: right;
       }
     }

+ 2 - 2
src/views/admin/logistics-licensed/club/index.vue

@@ -2,10 +2,10 @@
   <div class="app-container">
     <el-tabs v-model="activeName" @tab-click="handleClick">
       <el-tab-pane label="未寄送" name="first">
-        <club-list />
+        <club-list v-if="activeName === 'first'" :send-status="0" />
       </el-tab-pane>
       <el-tab-pane label="已寄送" name="second">
-        <club-list />
+        <club-list v-if="activeName === 'second'" :send-status="1" />
       </el-tab-pane>
     </el-tabs>
   </div>

+ 85 - 29
src/views/admin/logistics-licensed/components/club-list.vue

@@ -38,18 +38,11 @@
       <!-- <el-table-column label="创建人" class-name="status-col" width="160px" prop="createBy" /> -->
       <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 v-if="row.sendStatus === 0">
+            <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 warning">待上线</span>
+            <span style="margin-right: 10px" class="status danger">已寄送</span>
           </template>
         </template>
       </el-table-column>
@@ -69,7 +62,8 @@
           >
             查看设备认证
           </el-button>
-          <el-button type="primary" size="mini" @click="onSend(row)"> 寄送 </el-button>
+          <el-button v-if="sendStatus === 0" type="primary" size="mini" @click="onSend(row)"> 寄送 </el-button>
+          <el-button v-else type="primary" size="mini" @click="onLookRecord(row)"> 寄送记录 </el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -87,15 +81,14 @@
     <el-dialog title="机构授权牌寄送" :visible.sync="dialogVisible" width="40%">
       <el-form ref="ruleForm" :model="formData" :rules="rules" label-width="100px">
         <el-form-item label="快递公司:" prop="company">
-          <el-select v-model="formData.company" placeholder="请选择快递公司" clearable>
-            <el-option label="请选择快递公司" value="" />
-            <el-option label="顺丰快递" :value="1" />
-            <el-option label="京东快递" :value="2" />
-            <el-option label="圆通速递" :value="3" />
+          <el-select v-model="formData.companyId" placeholder="请选择快递公司" clearable>
+            <template v-for="item in companyList">
+              <el-option :key="item.id" :label="item.companyName" :value="item.id" />
+            </template>
           </el-select>
         </el-form-item>
-        <el-form-item label="物流编号:" prop="num">
-          <el-input v-model="formData.num" placeholder="请输入物流编号" />
+        <el-form-item label="物流编号:" prop="logisticsNumber">
+          <el-input v-model="formData.logisticsNumber" placeholder="请输入物流编号" />
         </el-form-item>
         <el-form-item label="图片备注:" prop="imageRemark">
           <el-input v-show="false" v-model="formData.imageRemark" />
@@ -104,15 +97,19 @@
             :multiple="true"
             :limit="6"
             accept=".jpg,.png"
+            :image-list="imageRemarkList"
+            :before-upload="beforeRemarkImageUpload"
+            @success="uploadRemarkImageSuccess"
+            @remove="handleRemarkImageRemove"
           />
         </el-form-item>
-        <el-form-item label="备注:" prop="remark">
-          <el-input v-model="formData.remark" type="textarea" rows="4" />
+        <el-form-item label="备注:" prop="remarks">
+          <el-input v-model="formData.remarks" type="textarea" rows="4" />
         </el-form-item>
       </el-form>
       <span slot="footer" class="dialog-footer">
         <el-button @click="dialogVisible = false">取 消</el-button>
-        <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
+        <el-button type="primary" @click="onSubmitLogistics">确 定</el-button>
       </span>
     </el-dialog>
   </div>
@@ -120,6 +117,7 @@
 
 <script>
 import { fecthAuthList } from '@/api/auth'
+import { fetchCompanyList, logisticsSend } from '@/api/logistics'
 import Pagination from '@/components/Pagination'
 import UploadImage from '@/components/UploadImage'
 import { formatDate } from '@/utils'
@@ -134,6 +132,12 @@ export default {
       return formatDate(time, 'yyyy-MM-DD HH:mm:ss')
     }
   },
+  props: {
+    sendStatus: {
+      type: Number,
+      default: 0
+    }
+  },
   data() {
     return {
       tableKey: 0,
@@ -147,18 +151,24 @@ export default {
         authUserId: '', // 供应商用户id
         pageNum: 1, // 页码
         pageSize: 10, // 分页
-        status: ''
+        status: '',
+        listType: 4,
+        sendStatus: ''
       },
       formData: {
-        company: '',
-        num: '',
-        imageRemark: '',
-        remark: ''
+        authId: '',
+        companyId: '',
+        logisticsNumber: '',
+        imageList: '',
+        remarks: '',
+        imageRemark: ''
       },
       rules: {
-        company: [{ required: true, message: '快递公司名称不能为空', trigger: ['blur'] }],
-        num: [{ required: true, message: '物流编号不能为空', trigger: ['blur'] }]
-      }
+        companyName: [{ required: true, message: '快递公司名称不能为空', trigger: ['blur'] }],
+        logisticsNumber: [{ required: true, message: '物流编号不能为空', trigger: ['blur'] }]
+      },
+      companyList: [],
+      imageRemarkList: []
     }
   },
   created() {
@@ -168,6 +178,7 @@ export default {
   methods: {
     // 获取授权列表
     getList() {
+      this.listQuery.sendStatus = this.sendStatus
       this.listLoading = true
       fecthAuthList(this.listQuery)
         .then((response) => {
@@ -194,9 +205,54 @@ export default {
 
     onSend(row) {
       console.log(row)
+      this.fetchCompanyList()
+      this.formData.authId = row.authId
       this.dialogVisible = true
     },
 
+    onLookRecord(row) {
+      console.log(row)
+      this.$router.push(`/logistics/licensed-record?id=${row.authId}`)
+    },
+
+    async onSubmitLogistics() {
+      try {
+        await logisticsSend(this.formData)
+        this.$message.success('发货成功')
+        this.dialogVisible = false
+        this.getList()
+      } catch (error) {
+        this.$message.error('发货失败')
+      }
+    },
+
+    async fetchCompanyList() {
+      try {
+        const res = await fetchCompanyList()
+        this.companyList = res.data
+      } catch (error) {
+        console.log(error)
+      }
+    },
+
+    uploadRemarkImageSuccess({ response, file, fileList }) {
+      this.imageRemarkList = fileList
+      this.formData.imageRemark = fileList.length
+      this.formData.imageList = fileList.map((item) => item.response.data)
+    },
+    handleRemarkImageRemove({ file, fileList }) {
+      this.imageRemarkList = fileList
+      this.formData.imageRemark = fileList.length
+      this.formData.imageList = fileList.map((item) => item.response.data)
+    },
+    beforeRemarkImageUpload(file) {
+      const flag = file.size / 1024 / 1024 < 1
+      if (!flag) {
+        this.$message.error('医疗许可证图片大小不能超过 1MB!')
+      }
+      return flag
+    },
+
     indexMethod(index) {
       return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1
     }

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

@@ -107,6 +107,12 @@ export default {
       return formatDate(time, 'yyyy-MM-DD HH:mm:ss')
     }
   },
+  props: {
+    sendStatus: {
+      type: Number,
+      default: 0
+    }
+  },
   // mixins: [scrollTo],
   data() {
     return {
@@ -122,7 +128,9 @@ export default {
         pageSize: 10, // 分页大小
         shopName: '', // 供应商名称
         shopType: '', // 供应商类型
-        loginAccount: '' // 登录账号
+        loginAccount: '', // 登录账号
+        listType: 7,
+        sendStatus: ''
       },
       list: [],
       prevData: ''
@@ -134,6 +142,7 @@ export default {
   methods: {
     // 获取列表数据
     getList() {
+      this.listQuery.sendStatus = this.sendStatus
       this.listLoading = true
       fetchSupplierList(this.listQuery)
         .then((res) => {

+ 2 - 2
src/views/admin/logistics-licensed/index.vue

@@ -2,10 +2,10 @@
   <div class="app-container">
     <el-tabs v-model="activeName" @tab-click="handleClick">
       <el-tab-pane label="未寄送" name="first">
-        <supplier-list />
+        <supplier-list v-if="activeName === 'first'" :send-status="0" />
       </el-tab-pane>
       <el-tab-pane label="已寄送" name="second">
-        <supplier-list />
+        <supplier-list v-if="activeName === 'second'" :send-status="1" />
       </el-tab-pane>
     </el-tabs>
   </div>

+ 99 - 0
src/views/admin/logistics-licensed/licensed-record.vue

@@ -0,0 +1,99 @@
+<template>
+  <div class="page-section">
+    <div class="app-container">
+      <div class="row">
+        <div class="col">货物名称:</div>
+        <div class="col">{{ detailData.authParty }}授权牌</div>
+      </div>
+      <div class="row">
+        <div class="col">物流公司:</div>
+        <div class="col">{{ detailData.companyName }}</div>
+      </div>
+      <div class="row">
+        <div class="col">物流单号:</div>
+        <div class="col">{{ detailData.logisticsNumber }}</div>
+      </div>
+
+      <div class="title">物流详情</div>
+      <el-divider />
+      <div class="info">
+        <div v-for="(item, index) in logisticInfo" :key="index" class="row">
+          <span class="time">[{{ item.time | formatTime }}]</span>
+          <span class="content">{{ item.context }}</span>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { logisticsDetails } from '@/api/logistics'
+export default {
+  data() {
+    return {
+      authId: '',
+      detailData: {},
+      logisticInfo: []
+    }
+  },
+  created() {
+    this.authId = this.$route.query.id
+    this.fetchLogisticsDetails()
+  },
+  methods: {
+    async fetchLogisticsDetails() {
+      try {
+        const res = await logisticsDetails({ authId: this.authId })
+        this.detailData = { ...this.detailData, ...res.data }
+        this.logisticInfo = res.data.info && JSON.parse(res.data.info)
+        console.log(this.logisticInfo)
+      } catch (error) {
+        console.log(error)
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.page-section {
+  width: 100%;
+  height: calc(100vh - 84px);
+  background: #f7f7f7;
+  box-sizing: border-box;
+  padding: 20px;
+}
+
+.app-container {
+  background: #fff;
+  box-sizing: border-box;
+  .row {
+    display: flex;
+    justify-content: flex-start;
+    align-items: flex-start;
+    .col {
+      line-height: 36px;
+      font-size: 14px;
+      color: #333;
+    }
+  }
+
+  .title {
+    font-size: 28px;
+    color: #409eff;
+    margin-top: 35px;
+  }
+
+  .info {
+    font-size: 14px;
+    line-height: 1.6;
+    .row {
+      margin: 12px 0;
+      .time {
+        margin-right: 16px;
+        white-space: nowrap;
+      }
+    }
+  }
+}
+</style>

+ 8 - 4
src/views/normal/club/device/edit.vue

@@ -67,7 +67,7 @@
       </el-form-item>
 
       <el-form-item label="购买渠道:">
-        <el-input v-model="formData.buyChannel" placeholder="请输入购买渠道" />
+        <el-input v-model="formData.purchaseWay" placeholder="请输入购买渠道" />
       </el-form-item>
 
       <el-form-item label="发票:">
@@ -143,7 +143,7 @@ export default {
         addQrCodeFlag: 0,
         addTemplateType: 1,
         productTypeId: '',
-        buyChannel: '', // 购买渠道
+        purchaseWay: '', // 购买渠道
         invoiceImage: ''// 发票
       },
       paramList: [], // 参数列表
@@ -236,6 +236,9 @@ export default {
           this.initParamList(4 - this.paramsCount)
         }
         this.initImageList()
+
+        this.invoiceImageList = [{ name: '', url: res.data.invoiceImage }]
+
         this.isLoading = false
       })
     },
@@ -297,9 +300,10 @@ export default {
         .then(res => {
           if (res.code !== 0) return
           const h = this.$createElement
+          const tip = this.editType === 'add' ? '添加' : '修改'
           this.$notify.success({
-            title: '新增设备',
-            message: h('i', { style: 'color: #333' }, `已添加设备`),
+            title: tip + '设备',
+            message: h('i', { style: 'color: #333' }, `已${tip}设备`),
             duration: 2000
           })
           this.$refs.addFormRef.resetFields()

+ 50 - 23
src/views/normal/club/edit.vue

@@ -32,8 +32,8 @@
       <el-form-item label="联系电话:" prop="mobile">
         <el-input v-model="formData.mobile" placeholder="请输入联系方式" clearable />
       </el-form-item>
-      <el-form-item label="手机号:" prop="phoneNumber">
-        <el-input v-model="formData.phoneNumber" placeholder="请输入手机号" clearable maxlength="11" />
+      <el-form-item label="手机号:" prop="userMobile">
+        <el-input v-model="formData.userMobile" placeholder="请输入手机号" clearable maxlength="11" show-word-limit />
       </el-form-item>
       <el-form-item label="机构logo:" prop="logoImage">
         <el-input v-show="false" v-model="formData.logoImage" />
@@ -58,7 +58,7 @@
       </el-form-item>
 
       <el-form-item label="机构类型:">
-        <el-radio-group v-model="formData.clubType">
+        <el-radio-group v-model="formData.firstClubType">
           <el-radio :label="1">医美</el-radio>
           <el-radio :label="2">生美</el-radio>
           <el-radio :label="3">项目公司</el-radio>
@@ -67,8 +67,8 @@
         </el-radio-group>
       </el-form-item>
 
-      <el-form-item label="医美类型:">
-        <el-radio-group v-model="formData.medicalType">
+      <el-form-item v-if="formData.firstClubType === 1" label="医美类型:">
+        <el-radio-group v-model="formData.secondClubType">
           <el-radio :label="1">诊所</el-radio>
           <el-radio :label="2">门诊</el-radio>
           <el-radio :label="3">医院</el-radio>
@@ -76,8 +76,16 @@
         </el-radio-group>
       </el-form-item>
 
-      <el-form-item label="医疗许可证:" prop="licenseImage">
-        <el-input v-show="false" v-model="formData.licenseImage" />
+      <el-form-item v-if="formData.firstClubType === 2" label="生美类型:">
+        <el-radio-group v-model="formData.secondClubType">
+          <el-radio :label="5">美容院</el-radio>
+          <el-radio :label="6">养生馆</el-radio>
+          <el-radio :label="7">其他</el-radio>
+        </el-radio-group>
+      </el-form-item>
+
+      <el-form-item label="医疗许可证:" prop="medicalLicenseImage">
+        <el-input v-show="false" v-model="formData.medicalLicenseImage" />
         <upload-image
           tip="请上传医疗许可证;建议尺寸:542px * 542px"
           :limit="1"
@@ -88,8 +96,8 @@
         />
       </el-form-item>
 
-      <el-form-item label="员工人数:" prop="memberCount">
-        <el-input v-model.number="formData.memberCount" placeholder="请输入员工人数" clearable />
+      <el-form-item label="员工人数:" prop="empNum">
+        <el-input v-model.number="formData.empNum" placeholder="请输入员工人数" clearable />
       </el-form-item>
 
       <el-form-item label="自定义属性:">
@@ -135,7 +143,7 @@ import UploadImage from '@/components/UploadImage'
 import { mapGetters } from 'vuex'
 import { saveBrandAuth, getAuthFormData } from '@/api/auth'
 import { getAddress } from '@/api/common'
-import { isPoint, isMobile } from '@/utils/validate'
+import { isPoint, isMobile, isNumber } from '@/utils/validate'
 
 export default {
   components: {
@@ -160,7 +168,7 @@ export default {
       if (value === '') {
         callback(new Error('联系方式不能为空'))
       } else {
-        if (isMobile(value)) {
+        if (isNumber(value)) {
           callback()
         } else {
           callback(new Error('联系方式格式不正确'))
@@ -193,15 +201,15 @@ export default {
         fullAddress: '',
         point: '',
         mobile: '',
-        phoneNumber: '',
+        userMobile: '',
         logoImage: '',
         banner: '',
         customFlag: 0,
         remarks: '',
-        memberCount: '',
-        clubType: 1,
-        medicalType: 1,
-        licenseImage: ''
+        empNum: '',
+        firstClubType: 1,
+        secondClubType: 1,
+        medicalLicenseImage: ''
       },
       rules: {
         name: [{ required: true, message: '机构名称不能为空', trigger: ['blur', 'change'] }],
@@ -212,9 +220,9 @@ export default {
         logoImage: [{ required: true, message: '请上传机构logo', trigger: 'change' }],
         banner: [{ required: true, message: '请至少上传一张banner图片', trigger: 'change' }],
         remarks: [{ required: true, message: '店铺备注不能为空', trigger: 'blur' }],
-        licenseImage: [{ required: true, message: '请上传医疗许可证', trigger: 'change' }],
-        memberCount: [{ required: true, message: '员工人数不能为空', trigger: 'change' }],
-        phoneNumber: [{ validator: validatePhoneNumber, trigger: 'change' }]
+        medicalLicenseImage: [{ required: true, message: '请上传医疗许可证', trigger: 'change' }],
+        empNum: [{ required: true, message: '员工人数不能为空', trigger: 'change' }],
+        userMobile: [{ validator: validatePhoneNumber, trigger: 'change' }]
       },
       // logo图片列表
       logoList: [],
@@ -298,6 +306,15 @@ export default {
         // this.formData.address = '广东省/深圳市/福田区'
         this.area = res.data.area
         this.address = res.data.area
+
+        this.formData.empNum = res.data.empNum
+        this.formData.firstClubType = res.data.firstClubType
+        this.formData.secondClubType = res.data.secondClubType
+        this.formData.medicalLicenseImage = res.data.medicalLicenseImage
+
+        this.formData.userMobile = res.data.userMobile
+
+        this.licenseImageList = [{ name: '', url: res.data.medicalLicenseImage }]
       })
     },
 
@@ -314,7 +331,12 @@ export default {
           logoImage: logo,
           point: lngAndLat,
           customFlag,
-          remarks
+          remarks,
+          empNum,
+          firstClubType,
+          secondClubType,
+          medicalLicenseImage,
+          userMobile
         } = this.formData
 
         const authUserId = this.proxyInfo?.authUserId || this.authUserId
@@ -332,7 +354,12 @@ export default {
           logo,
           lngAndLat,
           remarks,
-          customFlag
+          customFlag,
+          empNum,
+          firstClubType,
+          secondClubType,
+          medicalLicenseImage,
+          userMobile
         }
 
         data.bannerList = this.bannerList.map((item) => (item.response ? item.response.data : item.url))
@@ -398,11 +425,11 @@ export default {
     uploadLicenseImageSuccess({ response, file, fileList }) {
       this.licenseImageList = fileList
       console.log(this.licenseImageList)
-      this.formData.licenseImage = response.data
+      this.formData.medicalLicenseImage = response.data
     },
     handleLicenseImageRemove({ file, fileList }) {
       this.licenseImageList = fileList
-      this.formData.licenseImage = ''
+      this.formData.medicalLicenseImage = ''
     },
     beforeLicenseImageUpload(file) {
       const flag = file.size / 1024 / 1024 < 1

+ 36 - 7
src/views/normal/club/index.vue

@@ -32,7 +32,10 @@
       <div class="filter-control">
         <permission-button type="primary" @click="downLoadExportExcel">获取导入模板</permission-button>
         <permission-button type="primary" @click="handleExport(1)">一键下载授权牌</permission-button>
-        <permission-button type="primary" @click="handleExport(2)">一键下载二维码</permission-button>
+        <permission-button type="primary" @click="handleExport(3)">一键下载机构二维码</permission-button>
+      </div>
+      <div class="filter-control">
+        <permission-button type="primary" @click="handleExport(2)">一键下载设备二维码</permission-button>
       </div>
     </div>
     <!-- 表格区域 -->
@@ -95,7 +98,7 @@
       </el-table-column>
 
       <el-table-column label="创建人" class-name="status-col" width="160px" prop="createBy" />
-      <el-table-column label="操作" align="center" width="440px" class-name="small-padding fixed-width">
+      <el-table-column label="操作" align="center" width="540px" class-name="small-padding fixed-width">
         <template slot-scope="{ row }">
           <permission-button type="primary" size="mini" @click="$_navigationTo(`club-edit?type=edit&id=${row.authId}`)">
             编辑
@@ -104,8 +107,14 @@
           <permission-button type="primary" size="mini" @click="$_navigationTo(`device-list?id=${row.authId}`)">
             查看设备认证
           </permission-button>
-          <permission-button type="primary" size="mini" @click="createClubQrcode"> 二维码 </permission-button>
-          <permission-button type="primary" size="mini" @click="$_navigationTo(`logistics-licensed?id=${row.authId}`)">
+          <permission-button type="primary" size="mini" @click="createClubQrcode(row)"> 二维码 </permission-button>
+          <permission-button type="primary" size="mini" @click="cotyClubLink"> 复制链接 </permission-button>
+          <permission-button
+            type="primary"
+            size="mini"
+            :disabled="row.status !== 1"
+            @click="$_navigationTo(`logistics-licensed?id=${row.authId}`)"
+          >
             授权牌物流
           </permission-button>
         </template>
@@ -159,12 +168,18 @@
       </span>
     </el-dialog>
     <!-- dialog END -->
+
+    <!-- 二维码 -->
+    <transition name="fade">
+      <qrcode v-if="showQRcode" :qrcode-data="clubInfo" @close="showQRcode = false" />
+    </transition>
   </div>
 </template>
 
 <script>
 import PermissionButton from '@/views/components/PermissionButton'
 import FileUpload from '@/components/FileUpload'
+import Qrcode from '@/components/qrcode/club-qrcode.vue'
 import { fecthAuthList, saveBrandAuth, changeAuthStatus, removeAuth, authImportExcel } from '@/api/auth'
 import Pagination from '@/components/Pagination' // secondary package based on el-pagination
 import { mapGetters } from 'vuex'
@@ -172,7 +187,7 @@ import { formatDate } from '@/utils'
 import { debounce, downLoadWithATag } from '@/utils/tools'
 export default {
   name: 'ComplexTable',
-  components: { Pagination, FileUpload, PermissionButton },
+  components: { Pagination, FileUpload, PermissionButton, Qrcode },
   filters: {
     formatTime(time) {
       if (!time) {
@@ -183,6 +198,8 @@ export default {
   },
   data() {
     return {
+      showQRcode: false,
+      clubInfo: {},
       noticeTitle: '添加',
       dialogFlag: true, // 对话框状态
       tableKey: 0,
@@ -250,10 +267,15 @@ export default {
   },
   methods: {
     // 机构二维码
-    createClubQrcode() {
+    createClubQrcode(item) {
+      this.clubInfo = item
+      this.showQRcode = true
       console.log('机构二维码')
     },
 
+    // 复制链接
+    cotyClubLink() {},
+
     // 上传文件
     submitUpload() {
       this.$refs.dialogForm.validate((valid) => {
@@ -277,7 +299,14 @@ export default {
 
     // 导出下载授权牌 || 二维码
     async handleExport(type) {
-      const confirmText = type === 1 ? '授权牌' : '二维码'
+      let confirmText = ''
+      if (type === 1) {
+        confirmText = '授权牌'
+      } else if (type === 2) {
+        confirmText = '设备二维码'
+      } else {
+        confirmText = '机构二维码'
+      }
 
       const text = await this.$confirm(`确认下载所有${confirmText}?`, '提示', {
         confirmButtonText: '确定',

+ 51 - 8
src/views/normal/club/logistics-licensed.vue

@@ -3,29 +3,60 @@
     <div class="app-container">
       <div class="row">
         <div class="col">货物名称:</div>
-        <div class="col">机构名称+授权牌</div>
+        <div class="col">{{ detailData.authParty }}授权牌</div>
       </div>
       <div class="row">
         <div class="col">物流公司:</div>
-        <div class="col">顺丰到家</div>
+        <div class="col">{{ detailData.companyName }}</div>
       </div>
       <div class="row">
         <div class="col">物流单号:</div>
-        <div class="col">SDLAJ454654464646</div>
+        <div class="col">{{ detailData.logisticsNumber }}</div>
       </div>
 
       <div class="title">物流详情</div>
       <el-divider />
+      <div class="info">
+        <div v-for="(item, index) in logisticInfo" :key="index" class="row">
+          <span class="time">[{{ item.time | formatTime }}]</span>
+          <span class="content">{{ item.context }}</span>
+        </div>
+      </div>
     </div>
   </div>
 </template>
 
 <script>
-export default {}
+import { logisticsDetails } from '@/api/logistics'
+export default {
+  data() {
+    return {
+      authId: '',
+      detailData: {},
+      logisticInfo: []
+    }
+  },
+  created() {
+    this.authId = this.$route.query.id
+    this.fetchLogisticsDetails()
+  },
+  methods: {
+    async fetchLogisticsDetails() {
+      try {
+        const res = await logisticsDetails({ authId: this.authId })
+        this.detailData = { ...this.detailData, ...res.data }
+        this.logisticInfo = res.data.info && JSON.parse(res.data.info)
+        console.log(this.logisticInfo)
+      } catch (error) {
+        console.log(error)
+      }
+    }
+  }
+}
 </script>
 
 <style lang="scss" scoped>
-.page-section{
+.page-section {
   width: 100%;
   height: calc(100vh - 84px);
   background: #f7f7f7;
@@ -36,21 +67,33 @@ export default {}
 .app-container {
   background: #fff;
   box-sizing: border-box;
-  .row{
+  .row {
     display: flex;
     justify-content: flex-start;
     align-items: flex-start;
-    .col{
+    .col {
       line-height: 36px;
       font-size: 14px;
       color: #333;
     }
   }
 
-  .title{
+  .title {
     font-size: 28px;
     color: #409eff;
     margin-top: 35px;
   }
+
+  .info {
+    font-size: 14px;
+    line-height: 1.6;
+    .row {
+      margin: 12px 0;
+      .time {
+        margin-right: 16px;
+        white-space: nowrap;
+      }
+    }
+  }
 }
 </style>

+ 77 - 41
src/views/normal/user/index.vue

@@ -3,16 +3,24 @@
     <!-- 搜索区域 -->
     <div class="filter-container">
       <div class="filter-control">
-        <span>姓名:</span>
-        <el-input v-model="listQuery.name" placeholder="姓名" @keyup.enter.native="getList" />
+        <span>机构名称:</span>
+        <el-input v-model="listQuery.name" placeholder="机构名称" @keyup.enter.native="getList" />
       </div>
       <div class="filter-control">
         <span>手机号:</span>
         <el-input v-model="listQuery.mobile" placeholder="手机号" @keyup.enter.native="getList" />
       </div>
+      <div class="filter-control">
+        <span>状态:</span>
+        <el-select v-model="listQuery.status" clearable @change="getList">
+          <el-option label="全部" value="" />
+          <el-option label="启用" :value="1" />
+          <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="handleCreate">添加用户</permission-button>
+        <permission-button type="primary" @click="handleCreate">添加账号</permission-button>
       </div>
     </div>
     <!-- 搜索区域END -->
@@ -28,7 +36,12 @@
       header-row-class-name="tableHeader"
     >
       <el-table-column label="序号" :index="indexMethod" type="index" width="80px" align="center" />
-      <el-table-column label="机构名称" prop="name" align="center" />
+      <el-table-column label="机构名称" prop="name" align="center">
+        <template slot-scope="{ row }">
+          <span v-if="row.name">{{ row.name }}</span>
+          <span v-else>—</span>
+        </template>
+      </el-table-column>
       <el-table-column label="手机号" width="140" align="center">
         <template slot-scope="{ row }">
           <span v-if="row.mobile">{{ row.mobile }}</span>
@@ -52,20 +65,30 @@
           <span v-else>—</span>
         </template>
       </el-table-column>
+      <el-table-column label="状态" width="240px" 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>
+      </el-table-column>
       <el-table-column label="操作" width="200px" align="center">
         <template slot-scope="{ row }">
-          <permission-button
-            type="danger"
-            size="mini"
-            style="margin-right: 5px"
-            @click="handleEdit(row)"
-          >编辑</permission-button>
           <permission-button
             type="primary"
             size="mini"
             style="margin-right: 5px"
-            @click="handleRemove(row)"
-          >删除</permission-button>
+            @click="handleResetPwd(row)"
+          >重置密码</permission-button>
+          <permission-button type="primary" size="mini" @click="handleEdit(row)">编辑</permission-button>
         </template>
       </el-table-column>
     </el-table>
@@ -80,9 +103,9 @@
 
     <el-dialog title="添加用户" width="30%" :visible.sync="dialogVisible" @close="onDialogClose">
       <el-form ref="form" label-width="80px" :model="formData" :rules="rules">
-        <el-form-item label="姓名:" prop="name">
+        <!-- <el-form-item label="姓名:" prop="name">
           <el-input v-model="formData.name" placeholder="请输入姓名" />
-        </el-form-item>
+        </el-form-item> -->
         <el-form-item label="手机号:" prop="mobile">
           <el-input v-model="formData.mobile" placeholder="请输入手机号" maxlength="11" show-word-limit />
         </el-form-item>
@@ -100,13 +123,12 @@ import PermissionButton from '@/views/components/PermissionButton'
 import Pagination from '@/components/Pagination' // secondary package based on el-pagination
 import { formatDate } from '@/utils'
 import { mapGetters } from 'vuex'
-import { createClubUser, getAuthUserList, removeClubUser } from '@/api/auth'
+import { createClubUser, getAuthUserList, resetClubUserPassword } from '@/api/auth'
 import { isMobile } from '@/utils/validate'
 
 const resetFormData = () => ({
   clubUserId: '',
-  authId: '',
-  name: '',
+  authUserId: '',
   mobile: ''
 })
 
@@ -133,10 +155,12 @@ export default {
     return {
       total: 0,
       authId: '', // 机构id
+      editType: 'add',
       listLoading: false,
       listQuery: {
-        authId: '', // 机构id
+        authUserId: '', // 机构id
         name: '', // 用户名
+        status: '',
         mobile: '', // 手机号
         pageNum: 0, // 页码
         pageSize: 10 // 分页大小
@@ -146,7 +170,7 @@ export default {
       dialogVisible: false,
       formData: resetFormData(),
       rules: {
-        name: [{ required: true, message: '请输入用户姓名', trigger: ['blur'] }],
+        // name: [{ required: true, message: '请输入用户姓名', trigger: ['blur'] }],
         mobile: [
           { required: true, message: '请输入手机号', trigger: ['blur'] },
           { validator: validateMobile, message: '手机号格式不正确', trigger: ['blur'] }
@@ -155,10 +179,9 @@ export default {
     }
   },
   computed: {
-    ...mapGetters(['authUserId', 'authUserId'])
+    ...mapGetters(['authUserId'])
   },
   created() {
-    this.authId = parseInt(this.$route.query.id)
     this.getList()
   },
   methods: {
@@ -171,7 +194,7 @@ export default {
     // 获取列表数据
     async fetchUserList() {
       this.listLoading = true
-      this.listQuery.authId = this.authId
+      this.listQuery.authUserId = this.authUserId
       try {
         const res = await getAuthUserList(this.listQuery)
         this.list = res.data.list
@@ -186,16 +209,19 @@ export default {
     // 创建用户
     handleCreate() {
       this.dialogVisible = true
+      this.editType = 'add'
     },
     // 修改用户
     handleEdit(row) {
       this.formData.clubUserId = row.clubUserId
-      this.formData.authId = row.authId
-      this.formData.name = row.name
+      this.formData.authUserId = row.authUserId
       this.formData.mobile = row.mobile
       this.dialogVisible = true
+      this.editType = 'edit'
     },
 
+    handleChangeStatus() {},
+
     // 保存用户信息
     async onSave() {
       let valide = false
@@ -206,10 +232,10 @@ export default {
       }
       if (!valide) return
 
-      this.formData.authId = this.authId
+      this.formData.authUserId = this.authUserId
       try {
         await createClubUser(this.formData)
-        this.$message.success('添加用户成功')
+        this.$message.success(`${this.editType === 'add' ? '添加' : '修改'}用户成功`)
         this.fetchUserList()
         this.dialogVisible = false
       } catch (error) {
@@ -217,24 +243,34 @@ export default {
       }
     },
     // 删除用户
-    async handleRemove(row) {
-      let confirmType = ''
-      try {
-        confirmType = await this.$confirm('确认删除改用户?', '提示', {
-          confirmButtonText: '确认',
-          cancelButtonText: '取消',
-          type: 'warning'
-        })
-      } catch (error) {
-        console.log(error)
-      }
+    // async handleRemove(row) {
+    //   let confirmType = ''
+    //   try {
+    //     confirmType = await this.$confirm('确认删除改用户?', '提示', {
+    //       confirmButtonText: '确认',
+    //       cancelButtonText: '取消',
+    //       type: 'warning'
+    //     })
+    //   } catch (error) {
+    //     console.log(error)
+    //   }
 
-      if (!confirmType) return
+    //   if (!confirmType) return
 
+    //   try {
+    //     await removeClubUser({ clubUserId: row.clubUserId })
+    //     this.$message.success('删除用户成功')
+    //     this.fetchUserList()
+    //   } catch (error) {
+    //     console.log(error)
+    //   }
+    // },
+
+    // 重置密码
+    async handleResetPwd(row) {
       try {
-        await removeClubUser({ clubUserId: row.clubUserId })
-        this.$message.success('删除用户成功')
-        this.fetchUserList()
+        await resetClubUserPassword({ clubUserId: row.clubUserId })
+        this.$message.success('重置密码成功')
       } catch (error) {
         console.log(error)
       }