lizhenhao 2 gadi atpakaļ
vecāks
revīzija
c82d0f832d

+ 7 - 0
src/api/position/JobPositionService.js

@@ -29,6 +29,13 @@ export default class JobPositionService {
       params: {id: id}
     })
   }
+  getJobPositionByOff (id) {
+    return request({
+      url: '/job/job_position/getJobPositionByOff',
+      method: 'get',
+      params: {id: id}
+    })
+  }
   queryAllPosition () {
     return request({
       url: '/job/job_position/queryAllPosition',

+ 7 - 0
src/api/rank/RankService.js

@@ -15,6 +15,13 @@ export default class RankService {
       params: {id: id}
     })
   }
+  getRankByPosition (id) {
+    return request({
+      url: '/rank/rank/getRankByPosition',
+      method: 'get',
+      params: {id: id}
+    })
+  }
   save (inputForm) {
     return request({
       url: `/rank/rank/save`,

+ 39 - 0
src/api/roster/RosterService.js

@@ -0,0 +1,39 @@
+import request from '@/utils/httpRequest'
+
+export default class RosterService {
+  list (params) {
+    return request({
+      url: '/roster/base/list',
+      method: 'get',
+      params: params
+    })
+  }
+  queryById (id) {
+    return request({
+      url: '/roster/base/queryById',
+      method: 'get',
+      params: {id: id}
+    })
+  }
+  queryAllSupervisor () {
+    return request({
+      url: '/roster/base/queryAllSupervisor',
+      method: 'get',
+      params: {}
+    })
+  }
+  save (inputForm) {
+    return request({
+      url: `/roster/base/save`,
+      method: 'post',
+      data: inputForm
+    })
+  }
+  delete (ids) {
+    return request({
+      url: '/roster/base/delete',
+      method: 'delete',
+      params: {ids: ids}
+    })
+  }
+}

+ 68 - 7
src/api/sys/OSSService.js

@@ -107,11 +107,12 @@ export function fileName (file) {
   return fileName
 }
 
-export function beforeAvatarUpload (file) {
+export function beforeAvatarUpload (file, fileList, maxValue) {
   // 文件大小校验
-  const isLt2M = file.size / 1024 / 1024 < 1024
+  const isLt2M = file.size / 1024 / 1024 < maxValue
   if (!isLt2M) {
-    this.$message.error('文件大小不能超过 1G !')
+    fileList.splice(fileList.length - 1, 1)
+    console.log('文件大小不能超过 ' + maxValue + ' MB!')
   }
   return isLt2M
 }
@@ -129,7 +130,10 @@ export function exnameFix (file, isShow, names) {
   return true
 }
 
-export async function httpRequest (file, name, type) { // 阿里云OSS上传
+export async function httpRequest (file, name, type, maxValue) { // 阿里云OSS上传
+  if (!beforeAvatarUpload(file.file, [], maxValue)) {
+    return
+  }
   console.log('开始上传')
   // 判断扩展名
   const tmpcnt = file.file.name.lastIndexOf('.') // 获取.的下标
@@ -144,12 +148,12 @@ export async function httpRequest (file, name, type) { // 阿里云OSS上传
   const fileName = filePath + name + '.' + exname
   console.log(fileName, '文件名')
 
-  client.multipartUpload(fileName, file.file, {
-    progress: function (p, checkpoint) {
+  await client.multipartUpload(fileName, file.file, {
+    progress: await function (p, checkpoint) {
       file.onProgress({percent: Math.floor(p * 100)}) // 触发el-upload组件的onProgress方法
     }
     // mime: type,
-  }).then(function (result) {
+  }).then(await function (result) {
     console.log(result)
     if (result.res.status === 200) {
       // file.onSuccess(result) // 触发el-upload组件的onSuccess方法
@@ -160,3 +164,60 @@ export async function httpRequest (file, name, type) { // 阿里云OSS上传
     file.onError('上传失败') // 触发el-upload组件的onError方法,此方法会移除文件列表
   })
 }
+
+// eslint-disable-next-line no-unused-vars
+function getTemporaryByUrl (url) {
+  return request({
+    url: '/oss/file/getTemporaryUrl',
+    method: 'get',
+    params: {url: url}
+  })
+}
+
+export async function openWindowOnUrl (row) {
+  if (row.url === undefined || row.url === null || row.url === '') {
+    // Message.error('没有获取到文件的url')
+    return
+  }
+  let rowUrl = ''
+  let suffix = row.name.substring(row.name.lastIndexOf('.') + 1)
+  if (suffix === 'jpg' || suffix === 'png' || suffix === 'gif' || suffix === 'bmp' || suffix === 'jpeg') {
+    await getTemporaryByUrl(row.url).then((data) => {
+      // eslint-disable-next-line no-undef
+      onPreview(data.data)
+    })
+    return
+  }
+  await getTemporaryByUrl(row.url).then((data) => {
+    rowUrl = data.data
+  })
+  if (suffix === 'pdf') {
+    window.open('https://view.xdocin.com/xdoc?_xdoc=' + encodeURIComponent(rowUrl), '_blank')
+  } else if (suffix === 'rar' || suffix === 'zip' || suffix === 'jar' || suffix === '7z') {
+    window.open('http://ow365.cn/?i=30045&furl=' + encodeURIComponent(rowUrl), '_blank')
+  } else {
+    window.open('https://view.officeapps.live.com/op/view.aspx?src=' + encodeURIComponent(rowUrl), '_blank')
+  }
+}
+
+export async function toHref (row) {
+  if (row.url === null || row.url === undefined || row.url === '') {
+    // Message.error('没有获取到文件的url')
+    return
+  }
+  const link = document.createElement('a')
+  await getTemporaryByUrl(row.url).then((data) => {
+    const url = data.data // 完整的url则直接使用
+    // 这里是将url转成blob地址,
+    fetch(url).then(res => res.blob()).then(blob => { // 将链接地址字符内容转变成blob地址
+      link.href = URL.createObjectURL(blob)
+      link.download = row.name || '' // 下载文件的名字
+      // a.download = url.split('/')[url.split('/').length -1] //  // 下载文件的名字
+      document.body.appendChild(link)
+      link.click()
+      // 在资源下载完成后 清除 占用的缓存资源
+      window.URL.revokeObjectURL(link.href)
+      document.body.removeChild(link)
+    })
+  })
+}

+ 3 - 3
src/components/treeSelect/treeSelect.vue

@@ -8,7 +8,7 @@
         :show-checkbox="showCheckbox"
         :props="props"
         highlight-current
-        :node-key="props.value"    
+        :node-key="props.value"
         :default-expanded-keys="defaultExpandedKey"
         @check-change="handleCheckChange"
         @node-click="handleNodeClick">
@@ -179,7 +179,7 @@ export default {
         return
       }
       if (node['disabled']) {
-        this.$message.warning('节点(' + node[this.props.label] + ')被禁止选择,请重新选择。')
+        // this.$message.warning('节点(' + node[this.props.label] + ')被禁止选择,请重新选择。')
         return
       }
       if (this.isOnlySelectLeaf && node.children.length > 0) {
@@ -285,4 +285,4 @@ export default {
   .el-tree-node__content:hover{
     background-color: #f5f7fa;
   } */
-</style>
+</style>

+ 2 - 0
src/main.js

@@ -14,6 +14,7 @@ import '@/utils/filter'
 import validator from '@/utils/validator'
 import validatorXG from '@/utils/validatorXG'
 import validateXG from '@/utils/validateXG'
+import commonJS from '@/utils/common'
 import cloneDeep from 'lodash/cloneDeep'
 import lodash from 'lodash/object'
 import axios from 'axios'
@@ -153,6 +154,7 @@ Vue.prototype.$axios = axios
 Vue.prototype.validator = validator
 Vue.prototype.validatorXG = validatorXG
 Vue.prototype.validateXG = validateXG
+Vue.prototype.commonJS = commonJS
 Vue.prototype.lodash = lodash
 Vue.prototype.moment = moment
 Vue.prototype.deepClone = utils.deepClone

+ 37 - 0
src/utils/common.js

@@ -165,6 +165,7 @@ export default {
     }
   },
   /**
+   * 身份证号验证
    * @param {string} value
    */
   isIDCardNo(value) {
@@ -174,6 +175,42 @@ export default {
     } else {
       return true;
     }
+  },
+  /**
+   * 从身份证号中获取出生日期、性别、年龄
+   * @param idCard
+   * @returns {{sex: string, birth: null, age: number}}
+   */
+  decomposeIdCard(idCard) {
+    let sex = null
+    let birth = null
+    let myDate = new Date()
+    let month = myDate.getMonth() + 1
+    let day = myDate.getDate()
+    let age = 0
+
+    if (idCard.length === 18) {
+      age = myDate.getFullYear() - idCard.substring(6, 10) - 1
+      sex = idCard.substring(16, 17)
+      birth = idCard.substring(6, 10) + '-' + idCard.substring(10, 12) + '-' + idCard.substring(12, 14)
+      // eslint-disable-next-line no-mixed-operators
+      if (idCard.substring(10, 12) < month || idCard.substring(10, 12) === month && idCard.substring(12, 14) <= day) age++
+
+    }
+    if (idCard.length === 15) {
+      age = myDate.getFullYear() - idCard.substring(6, 8) - 1901
+      sex = idCard.substring(13, 14)
+      birth = '19' + idCard.substring(6, 8) + '-' + idCard.substring(8, 10) + '-' + idCard.substring(10, 12)
+      // eslint-disable-next-line no-mixed-operators
+      if (idCard.substring(8, 10) < month || idCard.substring(8, 10) === month && idCard.substring(10, 12) <= day) age++
+    }
+
+    if (sex % 2 === 0) {
+      sex = '2'  // 性别代码 1代表男,2代表女,暂时不涉及其他类型性别
+    } else {
+      sex = '1'
+    }
+    return {age, sex, birth}
   }
 
 }

+ 12 - 1
src/utils/validateXG.js

@@ -40,4 +40,15 @@ export function isLinkMobile (str) {
   return linkMobile.test(str)
 }
 
-export default {isMobile, isPhone, isBankNumber, isLinkMobile}
+/**
+ * 银行卡号验证
+ * 银行卡号:12位 16位 17 18 19
+ * @param str
+ * @returns {boolean}
+ */
+export function isBankNum (str) {
+  const bankNumber = /^([1-9]{1})(\d{11}|\d{15}|\d{16}|\d{17}|\d{18})$/
+  return bankNumber.test(str)
+}
+
+export default {isMobile, isPhone, isBankNumber, isLinkMobile, isBankNum}

+ 18 - 1
src/utils/validatorXG.js

@@ -1,4 +1,5 @@
 import validateXG from './validateXG'
+import validate from './validate'
 
 var isMobile = (rule, value, callback) => {
   if (value && !validateXG.isMobile(value)) {
@@ -32,4 +33,20 @@ var isLinkMobile = (rule, value, callback) => {
   }
 }
 
-export default {isMobile, isPhone, isBankNumber, isLinkMobile}
+var isIntGtZero = (rule, value, callback) => {
+  if (value && !validate.isIntGtZero(value)) {
+    callback(new Error('请输入大于0整数'))
+  } else {
+    callback()
+  }
+}
+
+var isBankNum = (rule, value, callback) => {
+  if (value && !validateXG.isBankNum(value)) {
+    callback(new Error('请输入正确的银行卡号'))
+  } else {
+    callback()
+  }
+}
+
+export default {isMobile, isPhone, isBankNumber, isLinkMobile, isIntGtZero, isBankNum}

+ 244 - 0
src/views/common/UpLoadComponent.vue

@@ -0,0 +1,244 @@
+<!--文件上传组件-->
+<template>
+  <div>
+    <el-divider content-position="left"><i class="el-icon-document"></i> 附件</el-divider>
+    <el-upload ref="upload" style="display: inline-block; :show-header='status'" action=""
+               :limit="999" :http-request="httpRequest"
+               multiple
+               :on-exceed="(files, fileList) =>{
+                      $message.warning(`当前限制选择 999 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`)
+                     }"
+               :show-file-list="false"
+               :on-change="changes"
+               :on-progress="uploadVideoProcess"
+               :file-list="fileList">
+      <el-button type="info" size="mini" :disabled="auth==='view'">点击上传</el-button>
+    </el-upload>
+    <div style="height: calc(100% - 80px);margin-top: 10px">
+      <!-- 进度条 -->
+      <el-progress style="margin-left: 5em" v-if="progressFlag" :percentage="loadProgress"></el-progress>
+      <el-table
+        ref="uploadTable"
+        :key="tableKey"
+        :data="dataListNew">
+        <el-table-column type="seq" width="40"></el-table-column>
+        <el-table-column label="文件名称" prop="name" align="center">
+          <template scope="scope">
+            <div v-if="ifName(scope.row) === true">
+              <el-image
+                style="width: 30px; height: 30px;padding-top: 4px"
+                :src="scope.row.lsUrl"
+                :preview-src-list="[scope.row.lsUrl]"
+              ></el-image>
+            </div>
+            <div v-else>
+              <el-link  type="primary" :underline="false" @click="showFile(scope.row)">{{scope.row.name}}</el-link>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="创建人" prop="createBy.name" align="center"></el-table-column>
+        <el-table-column label="创建时间" prop="createDate" align="center"></el-table-column>
+        <el-table-column label="操作" width="200px" fixed="right" align="center">
+          <template  scope="scope">
+            <el-button type="text"  icon="el-icon-edit" size="small" @click="toHref(scope.row)" :disabled="false">下载</el-button>
+            <el-button type="text"  icon="el-icon-delete" size="small"  @click="deleteById(scope.row, scope.$index)" :disabled="auth==='view'">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <el-image-viewer v-if="showViewer" :on-close="closeViewer" :url-list="[url]" :zIndex=9999></el-image-viewer>
+  </div>
+</template>
+
+<script>
+  // eslint-disable-next-line no-unused-vars
+  import OSSSerivce, {
+    httpRequest,
+    // eslint-disable-next-line no-unused-vars
+    handleRemove,
+    fileName,
+    // eslint-disable-next-line no-unused-vars
+    beforeAvatarUpload,
+    // eslint-disable-next-line no-unused-vars
+    openWindowOnUrl,
+    // eslint-disable-next-line no-unused-vars
+    toHref
+  } from '@/api/sys/OSSService'
+  import ElImageViewer from 'element-ui/packages/image/src/image-viewer'
+  import moment from 'moment'
+  export default {
+    data () {
+      return {
+        progressFlag: false,
+        loadProgress: 0,
+        fileList: [],
+        dataList: [],
+        dataListNew: [],
+        url: '',
+        showViewer: false,
+        ossService: null,
+        auth: '',
+        directory: 'public',
+        maxValue: 300,
+        tableKey: ''
+      }
+    },
+    watch: {
+    },
+    created () {
+      this.ossService = new OSSSerivce()
+    },
+    components: {
+      ElImageViewer
+    },
+    mounted () {
+      window.onPreview = this.onPreview
+    },
+    methods: {
+      /**
+       * 文件上传组件初始化
+       * @param auth
+       *    auth的值为"view"时,不可上传/编辑文件
+       *    auth为其他值时,可上传/编辑文件
+       * @param fileList  要显示到文件上传列表中的文件。
+       *    注:文件必须要有url属性并且文件的url属性值必须是在oss中的路径值
+       *    例:'/attachment-file/xxx/xxx/2022/9/08/xxx.jpg'
+       * @param directory  要存放到oss的哪个文件夹下。
+       *    注:值为空时,默认存放到"public"文件夹
+       * @param maxValue  上传文件允许的最大值,单位:MB
+       *    注:值为空时,默认值为300MB
+       */
+      async newUpload (auth, fileList, directory, maxValue) {
+        if (directory !== undefined && directory !== null && directory !== '' && directory !== {}) {
+          this.directory = directory
+        } else {
+          this.directory = 'public'
+        }
+        if (maxValue !== undefined && maxValue !== null && maxValue !== '' && maxValue !== 0) {
+          this.maxValue = maxValue
+        } else {
+          this.maxValue = 300
+        }
+        this.auth = auth
+        console.log(this.loading)
+        for await (let item of fileList) {
+          await this.ossService.getTemporaryUrl(item.url).then((data) => {
+            item.lsUrl = data.data
+            this.dataList.push(item)
+            this.dataListNew.push(item)
+          })
+        }
+        // this.dataList = JSON.parse(JSON.stringify(fileList))
+        // this.dataListNew = JSON.parse(JSON.stringify(fileList))
+      },
+      async httpRequest (file) {
+        await httpRequest(file, fileName(file), this.directory, this.maxValue)
+      },
+      uploadVideoProcess (event, file, fileList) {
+        this.progressFlag = true // 显示进度条
+        this.loadProgress = parseInt(event.percent) // 动态获取文件上传进度
+        if (this.loadProgress >= 100) {
+          this.loadProgress = 100
+          setTimeout(() => { this.progressFlag = false }, 1000) // 一秒后关闭进度条
+        }
+      },
+      async changes (file, fileList) {
+        // if (file.status !== 'ready') {
+        //   return
+        // }
+        if (!beforeAvatarUpload(file, fileList, this.maxValue)) {
+          this.$message.error('文件大小不能超过 ' + this.maxValue + ' MB!')
+          return
+        }
+        this.dataListNew = []
+        this.dataList.forEach((item) => {
+          this.dataListNew.push(item)
+        })
+        for (let item of fileList) {
+          item.createDate = moment(new Date()).format('YYYY-MM-DD HH:mm:ss')
+          item.createBy = {
+            id: '',
+            name: ''
+          }
+          item.createBy.id = this.$store.state.user.id
+          item.createBy.name = this.$store.state.user.name
+          this.dataListNew.push(item)
+        }
+        for await (let item of this.dataListNew) {
+          if (item.raw !== undefined && item.raw !== null && item.raw !== {}) {
+            item.url = item.raw.url
+            if (item.raw.url !== undefined && item.raw.url !== null && item.raw.url !== {}) {
+              await this.ossService.getTemporaryUrl(item.raw.url).then((data) => {
+                item.lsUrl = data.data
+              })
+            }
+          }
+        }
+        this.tableKey = Math.random()
+      },
+      showFile (row) {
+        openWindowOnUrl(row)
+      },
+      onPreview (url) {
+        this.url = url
+        this.showViewer = true
+      },
+      // 关闭查看器
+      closeViewer () {
+        this.url = ''
+        this.showViewer = false
+      },
+      toHref (row) {
+        toHref(row)
+      },
+      deleteById (row, index) {
+        this.dataListNew.splice(index, 1)
+        if (row.id !== null && row.id !== '' && row.id !== undefined) {
+          this.dataList.splice(index, 1)
+          // this.ossService.deleteMsgById(row.id)
+        } else {
+          let num
+          if (this.dataList.length > 0) {
+            num = this.dataList.length - 1
+          } else {
+            num = 0
+          }
+          this.$refs.upload.uploadFiles.splice(index - num, 1)
+        }
+      },
+      /**
+       * 关闭dialog时使用  清除el-upload中上传的文件
+       */
+      clearUpload () {
+        this.$refs.upload.uploadFiles = []
+        this.dataList = []
+        this.dataListNew = []
+      },
+      /**
+       * 获取当前文件列表中的文件数据
+       */
+      getDataList () {
+        return this.dataListNew
+      },
+      /**
+       * 判断进度条是否结束
+       * @returns {boolean}
+       */
+      checkProgress () {
+        if (this.progressFlag === true) {
+          this.$message.warning('请等待文件上传完成再进行提交')
+          return true
+        }
+        return false
+      },
+      ifName (row) {
+        let suffix = row.name.substring(row.name.lastIndexOf('.') + 1)
+        if (suffix === 'jpg' || suffix === 'png' || suffix === 'gif' || suffix === 'bmp' || suffix === 'jpeg') {
+          return true
+        } else {
+          return false
+        }
+      }
+    }
+  }
+</script>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1620 - 0
src/views/modules/roster/RosterForm.vue


+ 223 - 0
src/views/modules/roster/RosterList.vue

@@ -0,0 +1,223 @@
+<template>
+  <div class="page">
+    <el-form size="small" :inline="true" class="query-form" ref="searchForm" :model="searchForm" @keyup.enter.native="refreshList()" @submit.native.prevent>
+      <!-- 搜索框-->
+      <el-form-item prop="name">
+        <el-input size="small" v-model="searchForm.name" placeholder="姓名" clearable></el-input>
+      </el-form-item>
+      <el-form-item prop="idCard">
+        <el-input size="small" v-model="searchForm.idCard" placeholder="证件号" clearable></el-input>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" @click="refreshList()" size="small" icon="el-icon-search">查询</el-button>
+        <el-button @click="resetSearch()" size="small" icon="el-icon-refresh-right">重置</el-button>
+      </el-form-item>
+    </el-form>
+    <div class="bg-white top">
+      <vxe-toolbar :refresh="{query: refreshList}" custom>
+        <template #buttons>
+          <el-button v-if="hasPermission('roster:base:add')" type="primary" size="small" icon="el-icon-plus" @click="add()">新建</el-button>
+          <el-button v-if="hasPermission('roster:base:del')" type="danger"   size="small" icon="el-icon-delete" @click="del()" :disabled="$refs.rosterTable && $refs.rosterTable.getCheckboxRecords().length === 0" plain>删除</el-button>
+          <el-button v-if="showButton" type="primary" size="small" icon="el-icon-arrow-down" @click="showTabs()" plain>展示分类</el-button>
+          <el-button v-if="disableButton" type="primary" size="small" icon="el-icon-arrow-up" @click="disableTabs()" plain>收起分类</el-button>
+        </template>
+      </vxe-toolbar>
+      <el-tabs v-model="activeName" type="card" @tab-click="handleClick">
+        <el-tab-pane :key="index" v-for="(item,index) in workerTypeList" :label="item.label" :name="item.label" :value="item.value"></el-tab-pane>
+      </el-tabs>
+      <div style="height: calc(100% - 140px);">
+        <vxe-table
+          border="inner"
+          auto-resize
+          resizable
+          height="auto"
+          :loading="loading"
+          size="small"
+          ref="rosterTable"
+          show-header-overflow
+          show-overflow
+          highlight-hover-row
+          :menu-config="{}"
+          :print-config="{}"
+          :export-config="{}"
+          @sort-change="sortChangeHandle"
+          :sort-config="{remote:true}"
+          :data="dataList"
+          :import-config="{}"
+          :checkbox-config="{}">
+          <vxe-column type="seq" width="40"></vxe-column>
+          <vxe-column type="checkbox"  width="40px"></vxe-column>
+          <vxe-column title="姓名" field="name">
+            <template slot-scope="scope">
+              <el-link  type="primary" :underline="false" v-if="hasPermission('roster:base:view')"  @click="view(scope.row.id)">{{scope.row.name}}</el-link>
+              <span v-else>{{scope.row.name}}</span>
+            </template>
+          </vxe-column>
+          <vxe-column width="200px"  title="证件号" field="idCard" > </vxe-column>
+          <vxe-column width="200px"  title="员工类型" field="workerType" >
+            <template slot-scope="scope">
+              <span> {{$dictUtils.getDictLabel("worker_type", scope.row.workerType)}} </span>
+            </template>
+          </vxe-column>
+          <vxe-column width="200px"  title="入职日期" field="onboardingDate" >
+              <template slot-scope="scope">
+                {{ moment(scope.row.onboardingDate).format('YYYY-MM-DD')}}
+              </template>
+          </vxe-column>
+
+          <vxe-column title="操作" width="200px" fixed="right" align="center">
+            <template  slot-scope="scope">
+              <el-button v-if="hasPermission('roster:base:view')" type="text" icon="el-icon-view" size="small" @click="view(scope.row.id)">查看</el-button>
+              <el-button v-if="hasPermission('roster:base:edit')" type="text" icon="el-icon-edit" size="small" @click="edit(scope.row.id)">修改</el-button>
+              <el-button v-if="hasPermission('roster:base:del')" type="text"  icon="el-icon-delete" size="small" @click="del(scope.row.id)">删除</el-button>
+            </template>
+          </vxe-column>
+        </vxe-table>
+        <vxe-pager
+          background
+          size="small"
+          :current-page="tablePage.currentPage"
+          :page-size="tablePage.pageSize"
+          :total="tablePage.total"
+          :page-sizes="[10, 20, 100, 1000, {label: '全量数据', value: 1000000}]"
+          :layouts="['PrevPage', 'JumpNumber', 'NextPage', 'FullJump', 'Sizes', 'Total']"
+          @page-change="currentChangeHandle">
+        </vxe-pager>
+      </div>
+    </div>
+    <!-- 弹窗, 新增 / 修改 -->
+    <component is="RosterForm"  ref="rosterForm" @refreshDataList="refreshList"></component>
+  </div>
+</template>
+
+<script>
+  import RosterService from '@/api/roster/RosterService'
+  import RosterForm from './RosterForm'
+  export default {
+    data () {
+      return {
+        searchForm: {
+          name: ''
+        },
+        dataList: [],
+        tablePage: {
+          total: 0,
+          currentPag1e: 1,
+          pageSize: 10,
+          orders: []
+        },
+        loading: false,
+        activeName: 'working',
+        workerTypeList: [],
+        activeValue: '',
+        showButton: false,
+        disableButton: true
+      }
+    },
+    rosterService: null,
+    created () {
+      this.rosterService = new RosterService()
+      this.addTabs()
+    },
+    components: {
+      RosterForm
+    },
+    activated () {
+      this.refreshList()
+    },
+    methods: {
+      // 获取数据列表
+      refreshList () {
+        this.loading = true
+        this.rosterService.list({
+          'current': this.tablePage.currentPage,
+          'size': this.tablePage.pageSize,
+          'orders': this.tablePage.orders,
+          'workerType': this.activeValue,
+          ...this.searchForm
+        }).then(({data}) => {
+          this.dataList = data.records
+          this.tablePage.total = data.total
+          this.loading = false
+        })
+      },
+      // 当前页
+      currentChangeHandle ({ currentPage, pageSize }) {
+        this.tablePage.currentPage = currentPage
+        this.tablePage.pageSize = pageSize
+        this.refreshList()
+      },
+      // 排序
+      sortChangeHandle (column) {
+        this.tablePage.orders = []
+        if (column.order != null) {
+          this.tablePage.orders.push({column: this.$utils.toLine(column.property), asc: column.order === 'asc'})
+        }
+        this.refreshList()
+      },
+      // 新增
+      add () {
+        this.$refs.rosterForm.init('add', '')
+      },
+      // 修改
+      edit (id) {
+        id = id || this.$refs.rosterTable.getCheckboxRecords().map(item => {
+          return item.id
+        })[0]
+        this.$refs.rosterForm.init('edit', id)
+      },
+      // 查看
+      view (id) {
+        this.$refs.rosterForm.init('view', id)
+      },
+      // 删除
+      del (id) {
+        let ids = id || this.$refs.rosterTable.getCheckboxRecords().map(item => {
+          return item.id
+        }).join(',')
+        this.$confirm(`确定删除所选项吗?`, '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }).then(() => {
+          this.loading = true
+          this.rosterService.delete(ids).then(({data}) => {
+            this.$message.success(data)
+            this.refreshList()
+            this.loading = false
+          })
+        })
+      },
+      resetSearch () {
+        this.$refs.searchForm.resetFields()
+        this.refreshList()
+      },
+      handleClick (tab) {
+        const val = tab.$attrs.value
+        if (val === '0') {
+          this.activeValue = ''
+        } else {
+          this.activeValue = val
+        }
+        this.refreshList()
+      },
+      addTabs () {
+        this.workerTypeList = []
+        this.workerTypeList.push({'label': '在职', 'value': '0'})
+        this.$dictUtils.getDictList('worker_type').forEach(item => {
+          this.workerTypeList.push(item)
+        })
+      },
+      showTabs () {
+        this.addTabs()
+        this.showButton = false
+        this.disableButton = true
+      },
+      disableTabs () {
+        this.workerTypeList = []
+        this.showButton = true
+        this.disableButton = false
+      }
+    }
+  }
+</script>