Ver Fonte

'7月份修改'

hjs há 1 ano atrás
pai
commit
52a6ba47a2

+ 2 - 2
public/config.js

@@ -1,5 +1,5 @@
 window.g = {
-  // ApiUrl: 'http://192.168.11.11:9100/yx-fyzd', //本地
-  ApiUrl: 'https://tx.hz-hanghui.com:8088/yx-fyzd', //线上
+  // ApiUrl: 'http://192.168.11.11:9100/yx-fyzd' // 本地
+  ApiUrl: 'https://tx.hz-hanghui.com:8088/yx-fyzd' // 线上
 
 }

+ 26 - 0
src/api/visitee.js

@@ -0,0 +1,26 @@
+import request from '@/utils/request'
+// 获取受访人列表(分页)
+export function getVisiteePageList(data) {
+  return request({
+    url: '/admin/fkj/visitee/page',
+    method: 'post',
+    data
+  })
+}
+// 添加/编辑
+export function addOrUpdate(data) {
+  return request({
+    url: '/admin/fkj/visitee/add',
+    method: 'post',
+    data
+  })
+}
+
+// 删除指定区域
+export function deleteByIds(ids) {
+  return request({
+    url: '/admin/fkj/visitee/del',
+    method: 'post',
+    data: ids
+  })
+}

+ 186 - 0
src/components/BatchFileUpload/index.vue

@@ -0,0 +1,186 @@
+<template>
+  <a href="javascript:;" class="file">
+    {{ file && file.name ? file.name : '选择文件' }}
+    <input
+      id="fileSelect"
+      type="file"
+      accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel"
+      runat="server"
+      @change="upload"
+    >
+  </a>
+</template>
+
+<script>
+import * as XLSX from 'xlsx'
+export default {
+  name: 'BatchUploadFile',
+  props: {
+    // 除了第一行,跳过的行数,比如第二行为说明,不作为数据
+    range: {
+      type: Number,
+      default: 0
+    }
+  },
+  data() {
+    return {
+      file: null
+    }
+  },
+  methods: {
+    upload(e) {
+      // 若出现files赋值未知错误值或照片长度不对则return
+      if (!e.target.files || e.target.files.length < 1) {
+        return
+        // return this.$message.error('请上传excel文件')
+      }
+      // 如果是批量上传图片走这里
+      // if (this.file) {
+      //   if (!this.needFileNameList) {
+      //     return this.$message.error('请选择命名参数')
+      //   }
+      //   if (this.needFileNameList.indexOf('name') === -1) {
+      //     return this.$message.error('姓名为必填项')
+      //   }
+      //   if (this.needFileNameList.indexOf('idNumber') > -1 || this.needFileNameList.indexOf('cardIdEx') > -1 || this.needFileNameList.indexOf('phone') > -1) {
+      //     // 找出所有图片
+      //     this.getPhotoList(Array.from(files))
+      //   } else {
+      //     return this.$message.error('手机号、身份证、卡号任选其一必选')
+      //   }
+      // }
+
+      // 处理excel
+      this.file = e.target.files[0]
+      this.getJsonList(this.file)
+    },
+    // getPhotoList(files) {
+    //   const photoList = {
+    //     correct: [],
+    //     incorrect: []
+    //   }
+    //   files.forEach((item) => {
+    //     const arr = item.name.split('.')
+    //     const formatStyle = arr[arr.length - 1]
+    //     // 若文件类型不在指定类型中,则不处理
+    //     if (!this.formatStyles.includes(formatStyle)) {
+    //       photoList.incorrect.push({
+    //         reason: '文件格式要求为' + this.formatStyles.join(',') + ',上传的类型为' + formatStyle,
+    //         file: item
+    //       })
+    //       return
+    //     } else if (item.size > 1024 * 1024 * 2) {
+    //       // 要求文件大小不大于指定值 单位:字节
+    //       photoList.incorrect.push({
+    //         reason: '单张图片大小要求为2M内,上传的图片大小为' + item.size / 1024 / 1024 + 'M',
+    //         file: item
+    //       })
+    //       return
+    //     }
+
+    //     const obj = this.matchNeedFileNameList(item, arr[0])
+    //     photoList[obj.status ? 'correct' : 'incorrect'].push(obj.file)
+    //   })
+    //   this.doUpload(photoList)
+    // },
+    // matchNeedFileNameList(file, fileName) {
+    //   const arrContent = fileName.split('-')
+    //   const obj = {
+    //     status: true,
+    //     file: {}
+    //   }
+    //   if (arrContent.length < this.needFileNameList.length ||
+    //     arrContent.some((name) => {
+    //       return !name
+    //     })
+    //   ) {
+    //     return {
+    //       status: false,
+    //       file: {
+    //         reason: '文件没有按指定要求命名,需要' + this.needFileNameList.join(','),
+    //         file: file
+    //       }
+    //     }
+    //   }
+    //   this.needFileNameList.forEach((item, index) => {
+    //     obj.file[item] = arrContent[index].trim() || ''
+    //   })
+    //   obj.file['avatar'] = file
+    //   return obj
+    // },
+    doUpload(photoList) {
+      this.$emit('getFileList', photoList)
+    },
+    // 处理excel文件的内容
+    getJsonList(file) {
+      const reader = new FileReader()
+      const photoList = {
+        correct: [],
+        incorrect: []
+      }
+      reader.readAsBinaryString(file)
+      reader.onload = (e) => {
+        // 获取传递的表格
+        const binaryString = e.target.result
+        // 以二进制流方式读取到整份的excel 表格对象
+        const workbook = XLSX.read(binaryString, {
+          type: 'binary',
+          sheetRows: 0,
+          codepage: 936
+        })
+        let data = []
+        // 遍历每张表读取
+        for (const sheet in workbook.Sheets) {
+          const temp = XLSX.utils.sheet_to_json(workbook.Sheets[sheet])
+          if (temp && temp.length > 0) {
+            if (this.range > 0) {
+              temp.splice(0, this.range)
+            }
+            data = data.concat(temp)
+          }
+        }
+        photoList['correct'] = data
+        this.doUpload(photoList)
+      }
+    },
+    clearFile() {
+      this.file = null
+    }
+  }
+}
+</script>
+
+<style scoped>
+/*批量导入按钮*/
+.file {
+  position: relative;
+  background: #d0eeff;
+  border: 1px solid #99d3f5;
+  border-radius: 4px;
+  padding: 10px 20px;
+  box-sizing: border-box;
+  overflow: hidden;
+  color: #1e88c7;
+  text-decoration: none;
+  text-indent: 0;
+}
+.file input {
+  position: absolute;
+  font-size: 14px;
+  width: 100%;
+  height: 40px;
+  left: 0;
+  top: 0;
+  opacity: 0;
+  cursor: pointer;
+}
+.file:hover {
+  background: #aadffd;
+  border-color: #78c3f3;
+  color: #004974;
+  text-decoration: none;
+}
+.el-button {
+  margin-left: 20px;
+}
+</style>

+ 1 - 1
src/mixins/tableMixins.js

@@ -22,7 +22,7 @@ const tableMixins = {
   methods: {
     getFilterParams() {
       const params = {
-        pageNumber: this.pagination.current,
+        pageNum: this.pagination.current,
         pageSize: this.pagination.pageSize,
         data: { ...this.transformFilterForm() }
       }

+ 12 - 0
src/router/index.js

@@ -379,6 +379,18 @@ export const constantRoutes = [
       }
     ]
   },
+  {
+    path: '/visitee_list',
+    component: Layout,
+    children: [
+      {
+        path: 'index',
+        name: 'visitee_list',
+        component: () => import('@/views/visitee_list/index'),
+        meta: { title: '受访人列表', role: [1, 2, 3, 4, 5, 99], visitorType: ['2'], icon: 'el-icon-user-solid' }
+      }
+    ]
+  },
   // 404 page must be placed at the end !!!
   { path: '*', redirect: '/404', hidden: true }
 ]

+ 305 - 0
src/views/visitee_list/index.vue

@@ -0,0 +1,305 @@
+<template>
+  <div class="app-container">
+    <addModal ref="addModel" :user-list="user_list" :floor-list="floorList" @success="modalSuccess" />
+    <uploadModal ref="uploadModal" :user-list="user_list" @finish="modalSuccess(false)" />
+    <!--搜索区-->
+    <el-select
+      v-if="checkRole([1])"
+      v-model="form.adminId"
+      filterable
+      clearable
+      placeholder="请选择账号"
+    >
+      <el-option
+        v-for="item in user_list"
+        :key="item.adminId"
+        :label="item.username"
+        :value="item.adminId"
+      />
+    </el-select>
+    <el-input v-model="form.company" placeholder="请输入单位名称" class="margin-left input" />
+    <el-select v-model="form.floor" filterable clearable placeholder="请选择楼层" class="margin-left input" no-data-text="“选择楼层”为空">
+      <el-option
+        v-for="(item, index) in floorList"
+        :key="index"
+        :label="item.key"
+        :value="item.value"
+      />
+    </el-select>
+    <el-input v-model="form.name" placeholder="请输入姓名" class="margin-left input" />
+    <el-input v-model="form.phone" placeholder="请输入手机号" class="margin-left input" />
+    <el-input v-model="form.idNumber" placeholder="请输入身份证号" class="margin-left input" />
+    <el-input v-model="form.showTitle" placeholder="请输入显示标题" class="margin-left input" />
+    <el-input v-model="form.unitName" placeholder="请输入部门" class="margin-left input" />
+    <br>
+    <el-button type="primary" icon="el-icon-search" style="margin-top: 10px;" @click="query">搜索</el-button>
+    <el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-plus" @click="handleCreate">
+      添加
+    </el-button>
+    <el-button type="primary" icon="el-icon-download" style="margin-left: 10px;" @click="download">下载模板</el-button>
+    <el-button type="primary" style="margin-left: 10px;" plain @click="addOrUpdate">批量导入</el-button>
+    <!--主表格-->
+    <el-table
+      v-loading="tableLoading"
+      style="margin-top: 20px;"
+      :data="tableData"
+      stripe
+      element-loading-text="Loading"
+      border
+      fit
+      highlight-current-row
+    >
+      <el-table-column label="序号" align="center" width="80px">
+        <template slot-scope="scope">
+          {{ ((pagination.current - 1) * pagination.pageSize) + (scope.$index + 1) }}
+        </template>
+      </el-table-column>
+      <el-table-column v-if="checkRole([1])" label="所属账号" align="center">
+        <template slot-scope="scope">
+          {{ scope.row.username | matchNull }}
+        </template>
+      </el-table-column>
+      <el-table-column label="姓名" align="center">
+        <template slot-scope="scope">
+          {{ scope.row.name | matchNull }}
+        </template>
+      </el-table-column>
+      <el-table-column label="手机号" align="center">
+        <template slot-scope="scope">
+          <span>{{ scope.row.phone | matchNull }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="身份证号" align="center">
+        <template slot-scope="scope">
+          <span>{{ scope.row.idNumber | matchNull }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="单位名称" align="center">
+        <template slot-scope="scope">
+          {{ scope.row.company | matchNull }}
+        </template>
+      </el-table-column>
+      <el-table-column label="部门" align="center">
+        <template slot-scope="scope">
+          {{ scope.row.unitName | matchNull }}
+        </template>
+      </el-table-column>
+      <el-table-column label="楼层" align="center">
+        <template slot-scope="scope">
+          {{ scope.row.floor | matchNull }}
+        </template>
+      </el-table-column>
+      <el-table-column label="房间号" align="center">
+        <template slot-scope="scope">
+          {{ scope.row.room | matchNull }}
+        </template>
+      </el-table-column>
+      <el-table-column label="显示标题" align="center">
+        <template slot-scope="scope">
+          {{ scope.row.showTitle | matchNull }}
+        </template>
+      </el-table-column>
+      <el-table-column label="创建时间" align="center" :width="180">
+        <template slot-scope="scope">
+          {{ scope.row.createTime }}
+        </template>
+      </el-table-column>
+      <el-table-column align="center" prop="" label="操作区" :width="180">
+        <template slot-scope="{row,$index}">
+          <el-button type="primary" size="mini" @click="handleUpdate(row)">
+            编辑
+          </el-button>
+          <el-button size="mini" type="danger" @click="handleDelete(row, $index)">
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!--分页栏-->
+    <pagination
+      :total="pagination.total"
+      :page.sync="pagination.current"
+      :limit.sync="pagination.pageSize"
+      :page-sizes="pagination.pageSizeOptions"
+      :layout="pagination.layout"
+      @pagination="handleSizeChange"
+    />
+  </div>
+</template>
+
+<script>
+import { getAdminListNew } from '@/api/user_manage'
+import { checkRole } from '@/utils/checkRole'
+import { getVisiteePageList, deleteByIds } from '@/api/visitee'
+import tableMixins from '@/mixins/tableMixins'
+import Pagination from '@/components/Pagination'
+import AddModal from './modal/AddModal.vue'
+import UploadModal from './modal/UploadModal.vue'
+
+export default {
+  components: { Pagination, AddModal, UploadModal },
+  filters: {
+    matchNull(str) {
+      if (!str) {
+        return '暂无'
+      } else {
+        return str
+      }
+    }
+  },
+  mixins: [tableMixins],
+  data() {
+    return {
+      user_list: null,
+      form: {
+        adminId: null,
+        company: null,
+        floor: null,
+        name: null,
+        phone: null,
+        idNumber: null,
+        room: null,
+        showTitle: null,
+        unitName: null
+      }
+    }
+  },
+  computed: {
+    floorList() {
+      const temp = []
+      for (let i = 1; i <= 50; i++) {
+        temp.push({
+          key: `${i}楼`,
+          value: `${i}`
+        })
+      }
+      return temp
+    }
+  },
+  methods: {
+    // 查询权限
+    checkRole,
+    // 下载模板
+    download() {
+      window.location.href = process.env.VUE_APP_BASE_API + '/excel/visiteeListExcel.xlsx'
+    },
+    addOrUpdate() {
+      this.$refs.uploadModal.open()
+    },
+    initData() {
+      this.getTableList()
+      this.getAdminListNew(1, 1, 1)
+    },
+    // 获取账号列表数据
+    getAdminListNew(isNeedDistrict, isNeedEnterprise, isNeedPrivateArea) {
+      const data = {
+        isNeedDistrict, //	是否需要区级账号 1-需要(默认) 2-不需要
+        isNeedEnterprise, // 是否需要企业账号 1-需要(默认) 2-不需要
+        isNeedPrivateArea // 查询区域类型 1-通用(默认) 2-公有 3-私有
+      }
+      getAdminListNew(data).then((res) => {
+        this.user_list = res.data
+      })
+    },
+    // 获取表格数据
+    async getTableList() {
+      this.tableLoading = true
+      try {
+        const result = await getVisiteePageList(this.getFilterParams())
+        this.setDataList(result.data)
+      } catch (e) {
+        console.log(e)
+      } finally {
+        this.tableLoading = false
+      }
+    },
+    // 获取筛选信息
+    query() {
+      this.clearPageParams()
+      this.getTableList()
+    },
+    // 增加筛选条件
+    transformFilterForm() {
+      return this.form
+    },
+    modalSuccess(isEdit) {
+      if (!isEdit) {
+        this.clearPageParams()
+      }
+      this.getTableList()
+    },
+    handleCreate() {
+      this.$refs.addModel.open()
+    },
+    handleUpdate(row) {
+      this.$refs.addModel.open(Object.assign({}, row))
+    },
+    handleDelete(row) {
+      const that = this
+      this.$confirm('确定要删除此记录吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        showClose: false,
+        type: 'warning',
+        beforeClose: async(action, instance, done) => {
+          if (action === 'confirm') {
+            instance.confirmButtonLoading = true
+            instance.cancelButtonLoading = true
+            instance.confirmButtonText = '提交中...'
+            try {
+              await deleteByIds([row.id])
+              this.$message({
+                type: 'success',
+                message: '删除成功!'
+              })
+              that.getTableList()
+            } catch (e) {
+              // this.$message({
+              //   type: 'error',
+              //   message: '删除失败!'
+              // })
+            } finally {
+              done()
+              setTimeout(() => {
+                instance.confirmButtonLoading = false
+                instance.cancelButtonLoading = false
+              }, 300)
+            }
+          } else {
+            done()
+          }
+        }
+      }).then(() => {}).catch(() => {})
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+  .table{
+    margin-top: 15px;
+  }
+  .flex {
+    display: flex;
+    justify-content: flex-start;
+    align-items: center;
+  }
+  .margin-left {
+    margin: 10px 0 0 10px;
+  }
+  .input {
+    width: 200px;
+  }
+  ::-webkit-scrollbar{
+    width: 6px;
+    height: 6px;
+    background-color: #F1F2F5;
+  }
+
+::-webkit-scrollbar-thumb{
+  background-color:#BFC6D4;
+  border-radius: 10px;
+}
+::-webkit-scrollbar-track{
+  background-color: transparent;
+}
+</style>

+ 193 - 0
src/views/visitee_list/modal/AddModal.vue

@@ -0,0 +1,193 @@
+// 添加/修改
+<template>
+  <el-dialog
+    :title="isEdit ? '编辑受访人' : '添加受访人'"
+    width="500px"
+    :visible.sync="visible"
+    :destroy-on-close="false"
+    :close-on-click-modal="false"
+  >
+    <el-form ref="form" :rules="rules" :model="form" label-position="left" label-width="90px">
+      <el-form-item prop="id" style="margin-bottom: 0;">&nbsp;</el-form-item>
+      <el-form-item v-if="checkRole([1])" label="绑定账号" prop="adminId" required>
+        <el-select v-model="form.adminId" class="filter-item" placeholder="请选择账号" clearable filterable>
+          <el-option
+            v-for="item in userList"
+            :key="item.adminId"
+            :label="item.username"
+            :value="item.adminId"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="姓名" prop="name">
+        <el-input v-model="form.name" :disabled="nameReadOnly" placeholder="请输入姓名" maxlength="10" show-word-limit />
+      </el-form-item>
+      <el-form-item label="手机号" prop="phone">
+        <el-input v-model="form.phone" :disabled="phoneReadOnly" placeholder="请输入手机号" maxlength="15" show-word-limit />
+      </el-form-item>
+      <el-form-item label="身份证号" prop="idNumber">
+        <el-input v-model="form.idNumber" :disabled="idNumberReadOnly" placeholder="请输入身份证号" maxlength="18" show-word-limit />
+      </el-form-item>
+      <el-form-item label="单位名称" prop="company">
+        <el-input v-model="form.company" placeholder="请输入单位名称" maxlength="20" show-word-limit />
+      </el-form-item>
+      <el-form-item label="部门" prop="unitName">
+        <el-input v-model="form.unitName" placeholder="请输入部门" maxlength="20" show-word-limit />
+      </el-form-item>
+      <el-form-item label="楼层" prop="floor" required>
+        <el-select v-model="form.floor" class="filter-item" placeholder="请选择楼层" clearable>
+          <el-option v-for="(item, index) in floorList" :key="index" :label="item.key" :value="item.value" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="房间号" prop="room">
+        <el-input v-model="form.room" placeholder="请输入房间号" maxlength="20" show-word-limit />
+      </el-form-item>
+      <el-form-item label="显示标题" prop="showTitle" required>
+        <el-input v-model="form.showTitle" placeholder="请输入显示标题" maxlength="20" show-word-limit />
+      </el-form-item>
+    </el-form>
+    <div slot="footer" class="dialog-footer">
+      <el-button @click="visible = false">
+        取消
+      </el-button>
+      <el-button type="primary" :loading="submitLoading" @click="submit">
+        确定
+      </el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { checkRole } from '@/utils/checkRole'
+import { addOrUpdate } from '@/api/visitee'
+
+export default {
+  props: {
+    floorList: {
+      type: Array,
+      default: () => []
+    },
+    userList: {
+      type: Array,
+      default: () => []
+    }
+  },
+  data() {
+    return {
+      nameReadOnly: false,
+      phoneReadOnly: false,
+      idNumberReadOnly: false,
+      form: {
+        id: null,
+        adminId: null,
+        name: null,
+        phone: null,
+        idNumber: null,
+        company: null,
+        unitName: null,
+        floor: null,
+        room: null,
+        showTitle: null
+      },
+      rules: {
+        adminId: [
+          { required: true, type: 'number', message: '不能为空!', trigger: ['change', 'blur'] }
+        ],
+        idNumber: [
+          { max: 18, trigger: ['change', 'blur'], validator: (rule, value, callback) => {
+            if (!value) {
+              return callback()
+            }
+            if (value.length === 15) {
+              const idreg = /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$/
+              if (!idreg.test(value)) {
+                return callback('身份证号格式错误!')
+              }
+            } else if (value.length === 18) {
+              const idreg = /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/
+              if (!idreg.test(value)) {
+                return callback('身份证号格式错误!')
+              }
+            } else {
+              return callback('身份证号位数错误!')
+            }
+            return callback()
+          } }
+        ],
+        floor: [
+          { required: true, whitespace: true, message: '不能为空!', trigger: ['change', 'blur'] }
+        ],
+        showTitle: [
+          { required: true, whitespace: true, message: '不能为空!', trigger: ['change', 'blur'] }
+        ]
+      },
+      visible: false,
+      submitLoading: false,
+      isEdit: false
+    }
+  },
+  methods: {
+    checkRole,
+    open(obj) {
+      this.visible = true
+      this.submitLoading = false
+      this.$nextTick(() => {
+        this.$refs.form.resetFields()
+        if (obj && Object.keys(obj).length > 0) {
+          this.form = obj
+          this.isEdit = true
+          if (obj.name) {
+            this.nameReadOnly = true
+          }
+          if (obj.phone) {
+            this.phoneReadOnly = true
+          }
+          if (obj.idNumber) {
+            this.idNumberReadOnly = true
+          }
+        } else {
+          this.isEdit = false
+          this.nameReadOnly = false
+          this.phoneReadOnly = false
+          this.idNumberReadOnly = false
+        }
+      })
+    },
+    submit(e) {
+      e.preventDefault()
+      this.$refs.form.validate(async(valid) => {
+        if (!valid) {
+          return false
+        }
+        if (this.submitLoading) {
+          return
+        }
+        // if (!this.form.adminId) {
+        //   this.form.adminId = this.$store.getters.adminId
+        // }
+        delete this.form.createTime
+        this.submitLoading = true
+        try {
+          await addOrUpdate({ ...this.form })
+          this.visible = false
+          this.$emit('success', this.isEdit)
+        } catch (e) {
+          this.$refs.form.resetFields()
+          console.info('add', e)
+        } finally {
+          this.submitLoading = false
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style scoped>
+::v-deep .el-select {
+  width: 100%;
+}
+::v-deep .el-dialog__body {
+  padding-bottom: 0;
+}
+</style>

+ 328 - 0
src/views/visitee_list/modal/UploadModal.vue

@@ -0,0 +1,328 @@
+// 批量上传
+<template>
+  <div>
+    <el-dialog
+      title="批量导入"
+      width="500px"
+      :visible.sync="dialogVisible"
+      :destroy-on-close="false"
+      :close-on-click-modal="false"
+      @close="dialogClose"
+    >
+      <el-form ref="form" :rules="rules" :model="form" label-position="left" label-width="120px">
+        <el-form-item v-if="checkRole([1])" label="绑定账号" prop="adminId" required>
+          <el-select v-model="form.adminId" class="filter-item" placeholder="请选择账号" clearable filterable>
+            <el-option
+              v-for="item in userList"
+              :key="item.adminId"
+              :label="item.username"
+              :value="item.adminId"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="上传文件" prop="correctList">
+          <batch-file-upload ref="batchUploadRef" :range="1" @getFileList="batchUploadResult" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible = false">
+          取消
+        </el-button>
+        <el-button type="primary" @click="submit">
+          确定
+        </el-button>
+      </div>
+    </el-dialog>
+    <!-- 批量注册-抽屉 -->
+    <el-drawer
+      :title="hasCompleted ? '导入已完成' : '正在处理中..'"
+      :visible.sync="drawerVisible"
+      :wrapper-closable="false"
+      size="50%"
+      direction="rtl"
+    >
+      <div style="padding: 50px">
+        <div>
+          已处理条数;{{ hasDealNumber }}; 待处理条数:{{ waitDealNumber }};
+          总共条数:{{ allNumber }}
+        </div>
+        <el-progress
+          :percentage="makePercent"
+          :format="formatProgress"
+          style="margin-top: 10px"
+        />
+        <el-table
+          ref="batch_upload_result"
+          v-loading="false"
+          :data="batchUploadResultList"
+          class="table"
+          element-loading-text="Loading"
+          border
+          fit
+          highlight-current-row
+          height="500"
+        >
+          <el-table-column label="错误序号" align="center" width="100px">
+            <template slot-scope="scope">
+              {{ scope.$index + 1 }}
+            </template>
+          </el-table-column>
+          <el-table-column label="楼层" align="center">
+            <template slot-scope="scope">
+              {{ scope.row.floor }}
+            </template>
+          </el-table-column>
+          <el-table-column label="显示标题" align="center">
+            <template slot-scope="scope">
+              {{ scope.row.showTitle }}
+            </template>
+          </el-table-column>
+          <el-table-column label="身份证号" align="center">
+            <template slot-scope="scope">
+              {{ scope.row.idNumber }}
+            </template>
+          </el-table-column>
+          <el-table-column label="错误描述" align="center">
+            <template slot-scope="scope">
+              {{ scope.row.err }}
+            </template>
+          </el-table-column>
+        </el-table>
+        <div style="text-align: center; margin: 20px 0">
+          <el-button type="primary" @click="drawerVisible = false">
+            我已知晓
+          </el-button>
+          <el-button type="warning" @click="downloadBatchUploadErrorList">
+            下载错误列表文件
+          </el-button>
+        </div>
+      </div>
+    </el-drawer>
+  </div>
+</template>
+
+<script>
+import { checkRole } from '@/utils/checkRole'
+import { addOrUpdate } from '@/api/visitee'
+import BatchFileUpload from '@/components/BatchFileUpload'
+
+export default {
+  components: { BatchFileUpload },
+  props: {
+    userList: {
+      type: Array,
+      default: () => []
+    }
+  },
+  data() {
+    return {
+      form: {
+        adminId: null,
+        correctList: {
+          correct: [],
+          incorrect: []
+        }
+      },
+      rules: {
+        adminId: [
+          { required: true, type: 'number', whitespace: true, message: '不能为空!', trigger: ['change', 'blur'] }
+        ],
+        correctList: [
+          { required: true, type: 'object', message: '模板不能为空!', trigger: ['change', 'blur'], validator: (rule, value, callback) => {
+            if (Object.keys(value).length > 0 && ((value.correct && value.correct.length > 0) || (value.incorrect && value.incorrect.length > 0))) {
+              return callback()
+            }
+            return callback('数据不能为空!')
+          } }
+        ]
+      },
+      dialogVisible: false,
+      // 批量注册-处理提示值
+      hasDealNumber: 0,
+      waitDealNumber: 0,
+      allNumber: 0,
+      hasCompleted: false,
+      // 批量注册-抽屉控制值
+      drawerVisible: false,
+      batchUploadResultList: []
+    }
+  },
+  computed: {
+    // 批量注册-返回向下取整,减少渲染次数
+    makePercent() {
+      return Math.floor((this.hasDealNumber / this.allNumber) * 100)
+    }
+  },
+  created() {},
+  methods: {
+    checkRole,
+    open() {
+      this.dialogVisible = true
+      this.$nextTick(() => {
+        this.$refs.form.resetFields()
+      })
+    },
+    dialogClose() {
+      this.$refs.batchUploadRef.clearFile()
+    },
+    batchUploadResult(correctList) {
+      this.form.correctList = correctList
+    },
+    // 批量注册-操作
+    getFileList(correctList) {
+      this.hasCompleted = false
+      this.drawerVisible = true
+      this.hasDealNumber = correctList.incorrect.length
+      this.waitDealNumber = correctList.correct.length
+      this.allNumber = correctList.incorrect.length + correctList.correct.length
+      this.batchUploadResultList = correctList.incorrect.map((item) => {
+        return { name: item.name, err: item.reason }
+      })
+      this.makeScrollDown()
+      this.doSubmitUrl(correctList, 0)
+    },
+    // 批量注册-并提交至添加到接口
+    async doSubmitUrl(correctList, index) {
+      if (index <= correctList.correct.length - 1) {
+        const item = correctList.correct[index]
+        if (item['楼层'] && item['显示标题']) {
+          // 组装数据上传
+          const data = JSON.parse(JSON.stringify(this.form))
+          data.name = item['姓名'] || null
+          data.phone = item['手机号'] || null
+          data.idNumber = item['身份证号'] || null
+          data.company = item['单位名称'] || null
+          data.unitName = item['部门'] || null
+          data.floor = item['楼层']
+          data.room = item['房间号'] || null
+          data.showTitle = item['显示标题']
+          delete data.correctList
+
+          let hasValidate = true
+          if (data.idNumber) {
+            if (data.idNumber === 15) {
+              const idreg = /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$/
+              if (!idreg.test(data.idNumber)) {
+                this.batchUploadResultList.push({
+                  floor: data.floor,
+                  showTitle: data.showTitle,
+                  idNumber: data.idNumber,
+                  err: '身份证号格式错误'
+                })
+                hasValidate = false
+              }
+            } else if (data.idNumber === 18) {
+              const idreg = /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/
+              if (!idreg.test(data.idNumber)) {
+                this.batchUploadResultList.push({
+                  floor: data.floor,
+                  showTitle: data.showTitle,
+                  idNumber: data.idNumber,
+                  err: '身份证号格式错误'
+                })
+                hasValidate = false
+              }
+            } else {
+              this.batchUploadResultList.push({
+                floor: data.floor,
+                showTitle: data.showTitle,
+                idNumber: data.idNumber,
+                err: '身份证号位数错误'
+              })
+              hasValidate = false
+            }
+          }
+          if (hasValidate) {
+            try {
+              await addOrUpdate(data)
+            } catch (err) {
+              this.batchUploadResultList.push({
+                floor: data.floor,
+                showTitle: data.showTitle,
+                idNumber: data.idNumber,
+                err: err
+              })
+            }
+          }
+        } else {
+          this.batchUploadResultList.push({
+            name: item['姓名'] || '',
+            phone: item['手机号'] || '',
+            idNumber: item['身份证号'] || '',
+            company: item['单位名称'] || '',
+            unitName: item['部门'] || '',
+            floor: item['楼层'] || '',
+            room: item['房间号'] || '',
+            showTitle: item['显示标题'] || '',
+            err: '不包含 "楼层" 或 "显示标题" 字段'
+          })
+        }
+        this.hasDealNumber += 1
+        this.waitDealNumber -= 1
+        this.makeScrollDown()
+        // 继续调用
+        this.doSubmitUrl(correctList, ++index)
+      } else {
+        this.hasCompleted = true
+        this.$emit('finish')
+      }
+    },
+    // 批量注册人员-保持滚动条在最底部
+    makeScrollDown() {
+      this.$nextTick(() => {
+        this.$refs.batch_upload_result.$refs.bodyWrapper.scrollTop = this.$refs.batch_upload_result.$refs.bodyWrapper.scrollHeight
+      })
+    },
+    // 批量注册-返回进度条尾部显示值
+    formatProgress(percent) {
+      return percent === 100 ? '已完成' : ''
+    },
+    // 批量注册-导出错误名单
+    downloadBatchUploadErrorList() {
+      const list = this.batchUploadResultList
+      let string = '序号\t楼层\t显示标题\t身份证号\t错误原因\n'
+      for (let i = 0; i < this.batchUploadResultList.length; i++) {
+        string +=
+          (i + 1).toString() +
+          '\t' +
+          list[i].floor +
+          '\t' +
+          list[i].showTitle +
+          '\t' +
+          list[i].idNumber || '' +
+          '\t' +
+          list[i].err +
+          '\t' +
+          '\n'
+      }
+      const blob = new Blob([string], { type: 'text/plain;charset=utf-8' })
+      const excel_url = window.URL.createObjectURL(blob)
+      const link = document.createElement('a')
+      link.href = excel_url
+      link.download = '批量注册结果错误名单.xls'
+      document.body.appendChild(link)
+      link.click()
+      document.body.removeChild(link)
+    },
+    submit(e) {
+      e.preventDefault()
+      this.$refs.form.validate((valid) => {
+        if (!valid) {
+          return false
+        }
+        this.dialogVisible = false
+        this.getFileList(this.form.correctList)
+      })
+    }
+  }
+}
+</script>
+
+<style scoped>
+::v-deep .el-select {
+  width: 100%;
+}
+.table {
+  margin-top: 15px;
+}
+</style>