Day07-员工管理-上传下载

1.员工管理-导出excel

在这里插入图片描述
在这里插入图片描述

  • 导出员工接口返回的是二进制
  • axios配置responseType为blob接收二进制流文件为Blob格式
  • 按装file-saver包,实现下载Blob文件
  • npm install add file-saver
  • 导出员工excel的接口 (src/api/employee.js)
export function exportEmployee(){
  return request({
     url:'/sys/user/export',
     //改变接收数据的类型
     responseType:'blob'//使用blob接收二进制文件流
   })
}
  • 拦截器判断是不是blob类型,如果是 直接返回数据,不再进行解构(src/utils/request.js)
//响应拦截器
service.interceptors.response.use((response)=>{
  if(response.data instanceof Blob){
    return response.data
   }
})
  • 点击按钮调用接口,使用file-saver将Blob转化成文件下载
 <el-button size="mini" @click="exportEmployee">excel导出</el-button>
import FileSaver from 'file-saver'
import { exportEmployee } from '@/api/employee'
methods:{
  async exportEmployee(){
     const result = await exportEmployee()//导出所有的员工
     console.log(result)//使用一个npm包 直接将blob文件下载到本地 file-saver
     FileSaver.saveAs(result,'员工信息表.xlsx')
   }
}

2.员工管理-excel组件

在这里插入图片描述
在这里插入图片描述

  • 创建员工导入组件(src/views/employee/components/import-excel.vue)
 <el-dialog width="500px" title="员工导入" :visible="showExcelDialog" @close="$emit('update:showExcelDialog',false)">
     <el-row type="flex" justify="center">
        <div class="upload-excel">
            <input type="file" accept=".xlsx,.xls" ref="excel-upload-input" >
            <div class="drop">
                <i class="el-icon-upload"></i>
                <el-button type="text">下载导入模板</el-button>
                <span>将文件拖到此处或
                    <el-button type="text" >点击上传</el-button>
                </span>
            </div>
        </div>
     </el-row>
     <el-row type="flex" justify=" end">
        <!-- update:props属性名,值 直接修改 .sync修饰符的属性值 -->
        <el-button size="mini" type="primary" @click="$emit('update:showExcelDialog')"></el-button>
     </el-row>createError.js?2d83:16 Uncaught (in promise) Error: Request failed with status code 429
   </el-dialog>
  • 在员工管理页面-导入该组件并注册使用(src/views/employee/index.vue)
import ImportExcel from './components/import-excel.vue'
export default{
data(){
  showExcelDialog:false//控制excel的弹窗显示和隐藏
},
  components:{
    ImportExcel
   }
}
  • 使用该组件,并且应用变量(src/views/employee/index.vue)
<import-excel :show-excel-dialog.sync = "showExcelDialog" />
  • 点击excel导入按钮
<el-button size='mini' @click="showExcelDialog = true">excel导入</el-button>

3、下载导入模板

在这里插入图片描述
在这里插入图片描述

  • 下载模板的api(src/api/employee.js)
// 下载导入模板
export function getExportTemplate(){
	return request({
		url:'/sys/user/import/template',
		responseType:'blob'//二进制文件流 
	})
}
  • 点击按钮进行下载(src/views/employee/components/import-excel.vue)
<el-button type='text' @click="getTemplate">下载导入模板</el-button>
async getTemplate(){
	const data = await getExportTemplate();
	FileSaver.saveAs(data,'员工导入模板.xlsx')
}

4.员工管理-员工导入-上传excel

在这里插入图片描述
在这里插入图片描述

  • 上传excel的api(src/api/employee.js)
export function uploadExcel(data){
	return request({
		url:'/sys/user/import',
		method:'post',
		data //form-data类型  
	})
}
  • 点击上传-弹出文件选择框(src/views/employee/components/import-excel.vue)
<el-button type="text" @click="handleUpload">点击上传</el-button>
handleUpload(){
	this.$refs['excel-upload-input'].click()
}
  • 监听文件改变-上传excel-关闭弹窗(src/views/employee/components/import-excel.vue)
    JavaScript
<input ref="excel-upload-input" class="excel-upload-input" type="file" accept=".xlsx, .xls" @change="uploadChange" />
async uploadChange(event){
	console.log(event.target.files)
	const files = event.target.files //input的文件列表
	if(files.length > 0){
	  //大于0 说明有文件要上传
	  const data = new FormData()
	  //file:file类型
	  data.append('file',files[0])//将文件参数加入到formData中
	  try{
	  	await uploadExcel(data)
	  	//成功
	  	this.$emit('uploadSuccess') //通知父组件 上传成功
	  	this.$emit('update:showExcelDialog',false)//关闭弹层
	  }catch{
	   //捕获失败
	   //this.$refs['excel-upload-input'].value= ''
	   }finally{
	    //不论成功或者失败都执行finally
	    this.$refs['excel-upload-input'].value=''
	    }
	 }
}
  • 不论成功或者失败,再点击上传都会去选择一个新的excel,使用finally等到最后,将内容清空。
  • 父组件需要监听上传成功的事件(src/views/employee/index.vue)
<import-excel :show-excel-dialog.sync="showExcelDialog" @uploadSuccess="getEmployeeList"></import-excel>

5.员工管理-删除员工

在这里插入图片描述
在这里插入图片描述

  • 删除员工的接口-位置(src/api/employee.js)
//删除员工
export function delEmployee(id){
  return request({
   method:'delete',
   url:`/sys/user/${id}`
   })
}
  • 气泡确认位置(src/views/employee/index.vue)
 <template v-slot="{row}">
            <el-button size="mini" type="text">查看</el-button>
            <el-button size="mini" type="text">角色</el-button>
            <el-popconfirm trigger="hover" title="确认删除该行数据吗?" @onConfirm="confirmDel(row.id)">
              <el-button slot="reference" style="margin-left:10px" size="mini" type="text">删除</el-button>
            </el-popconfirm>
          </template>
  • 删除方法
async confirmDel(id){
  await delEmployee(id){
    if(this.list.length === 1 && this.queryParams.page > 1) this.queryParams.page--
    this.getEmployeeList()
    this.$message.success('删除成功')
   }
}

6.员工详情和路由

在这里插入图片描述

  • 创建一个员工详情组件-位置(src/views/employee/detail.vue)
<template>
  <div class="dashboard-container">
    <div class="app-container">
      <div class="edit-form">
        <el-form ref="userForm" label-width="220px">
          <!-- 姓名 部门 -->
          <el-row>
            <el-col :span="12">
              <el-form-item label="姓名" prop="username">
                <el-input size="mini" class="inputW" />
              </el-form-item>
            </el-col>

          </el-row>
          <!-- 工号 入职时间 -->
          <el-row>
            <el-col :span="12">
              <el-form-item label="工号" prop="workNumber">
                <el-input size="mini" class="inputW" />
              </el-form-item>
            </el-col>
          </el-row>
          <!--手机 聘用形式  -->
          <el-row>
            <el-col :span="12">
              <el-form-item label="手机" prop="mobile">
                <el-input
                  size="mini"
                  class="inputW"
                />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row>
            <el-col :span="12">
              <el-form-item label="部门" prop="departmentId">
                <!-- 放置及联部门组件 -->
              </el-form-item>
            </el-col>
          </el-row>
          <el-row>
            <el-col :span="12">
              <el-form-item label="聘用形式" prop="formOfEmployment">
                <el-select size="mini" class="inputW" />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row>
            <el-col :span="12">
              <el-form-item label="入职时间" prop="timeOfEntry">
                <el-date-picker
                  size="mini"
                  type="date"
                  value-format="yyyy-MM-dd"
                  class="inputW"
                />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row>
            <el-col :span="12">
              <el-form-item label="转正时间" prop="correctionTime">
                <el-date-picker
                  size="mini"
                  type="date"
                  class="inputW"
                />
              </el-form-item>
            </el-col>
          </el-row>
          <!-- 员工照片 -->
          <el-row>
            <el-col :span="12">
              <el-form-item label="员工头像">
                <!-- 放置上传图片 -->
              </el-form-item>
            </el-col>
          </el-row>
          <!-- 保存个人信息 -->
          <el-row type="flex">
            <el-col :span="12" style="margin-left:220px">
              <el-button size="mini" type="primary">保存更新</el-button>
            </el-col>
          </el-row>
        </el-form>
      </div>

    </div>
  </div>
</template>

<script>

export default {

}
</script>

<style scoped lang="scss">
    .edit-form {
      background: #fff;
      padding: 20px;
      .inputW {
        width: 380px
      }
    }

</style>
  • 配置员工详情路由信息(src/router/modules/employee.js)
{
        path:'/employee/detail',//员工详情地址
        component:()=>import('@/view/employee/detail.vue'),
        hidden:true,//隐藏在左侧菜单
        meta:{
            title:'员工详情' //显式在导航的文本
        }
    }
  • 点击添加员工跳转到详情页(src/views/employee/index.vue)
<el-button size="mini" type="primary" @click="$router.push('/employee/detail')">添加员工</el-button>

7.员工详情-表单数据校验

  • 姓名-必填-1-4个字符
  • 手机号-必填-格式校验
  • 部门-必填
  • 聘用形式-必填
  • 入职时间-必填
  • 转正时间-必填-不能小于入职时间
  • 定义数据和规则(src/views/employee/detail.vue)
<el-form label-width="220px" ref="userForm" :model="userInfo" :rules="rules" >
                <!-- 姓名 部门 -->
                <el-row>
                    <el-col :span="12">
                        <el-form-item prop="username" label="姓名" >
                            <el-input v-model="userInfo.username" size="mini" class="inputW">

                            </el-input>
                        </el-form-item>
                    </el-col>
                </el-row>
                <!-- 工号 入职时间 -->
                <el-row>
                    <el-col :span="12">
                        <el-form-item prop="workNumber" label="工号" >
                            <!-- 工号是系统生成的  -->
                            <el-input v-model="userInfo.workNumber" disabled size="mini" class="inputW"></el-input>
                        </el-form-item>
                    </el-col>
                </el-row>
                 <!-- 手机 聘用形式 -->
                 <el-row>
                    <el-col :span="12">
                        <el-form-item prop="mobile" label="手机" >
                            <el-input v-model="userInfo.mobile" size="mini" class="inputW"></el-input>
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row>
                    <el-col :span="12">
                        <el-form-item prop="departmentId" label="部门" >
                            <!-- 级联部门组件 -->
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row>
                    <el-col :span="12">
                        <el-form-item prop="formOfEmployment" label="聘用形式" >
                           <el-select v-model="userInfo.formOfEmployment" size="mini" class="inputW">
                            <el-option label="正式" :value="1" />
                            <el-option label="非正式" :value="2" />
                        </el-select>
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row>
                    <el-col :span="12">
                        <el-form-item prop="timeOfEntry" label="入职时间" >
                          <el-date-picker v-model="userInfo.timeOfEntry" size="mini" type="date" value-format="yyyy-MM-dd" class="inputW"></el-date-picker>
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row>
                    <el-col :span="12">
                        <el-form-item prop="correctionTime" label="转正时间" >
                          <el-date-picker v-model="userInfo.correctionTime" size="mini" type="date"  class="inputW"></el-date-picker>
                        </el-form-item>
                    </el-col>
                </el-row>
                <!-- 员工照片 -->
                <el-row>
                    <el-col :span="12">
                        <el-form-item label="员工头像">
                            <!-- 放上传图片 -->
                        </el-form-item>
                    </el-col>
                </el-row>
                <!-- 保存个人信息 -->
                <el-row type="flex">
                    <el-col :span="12" style="margin-left:220px;">
                       <el-button size="mini" @click="saveData" type="primary">保存更新</el-button>
                    </el-col>
                </el-row>
            </el-form>
 data() {
    return {
        userInfo:{
            username:'',//用户名
            mobile:'',//手机号
            workNumber:'',//工号
            formOfEmployment:null,//聘用形式
            departmentId:null,//部门id
            timeOfEntry:'',//入职时间
            correctionTime:''//转正时间
        },
        rules:{
            username:[
                {
                    required:true,message:'请输入姓名',trigger:'blur'
                },
                {
                    min:1,max:4,message:'姓名为1-4位'
                }
            ],
            mobile:[
                {
                    required:true,
                    message:'请输入手机号',
                    trigger:'blur'
                },
                {
                    pattern:/^1[3-9]\d{9}$/,
                    message:'手机号格式不正确',
                    trigger:'blur'
                }
            ],
            formOfEmployment:[
                {
                    required:true,
                    message:'请选择聘用形式',
                    trigger:'blur'
                }
            ],
            departmentId:[
                {
                    required:true,
                    message:'请选择部门',
                    trigger:'blur'
                }
            ],
            timeOfEntry:[
                {
                    required:true,
                    message:'请选择入职时间',
                    trigger:'blur'
                }
            ],
            correctionTime:[
                {
                    required:true,
                    message:'请选择转正时间',
                    trigger:'blur'
                },
                {
                    validator:(rule,value,callback)=>{
                        if(this.userInfo.timeOfEntry) {
                            if(new Date(this.userInfo.timeOfEntry) > new Date(value)){
                                callback(new Error('转正时间不能小于入职时间'))
                                return
                            }
                        }
                        callback()
                    }
                }
            ]

        }

    }
  },
  methods: {
    saveData(){
        this.$refs.userForm.validate()
    }
  }

8.员工详情-部门级联组件

  • Cascader级联组件的特性
  • options为一个树形结构的数据源
  • props可以设置数据源中的字段例如 label(展示) value(存取)
  • separator为展示的分隔符
    在这里插入图片描述
  • 创建select-tree组件(src/views/employee/components/select-tree.vue)
<template>
  <el-cascader size="mini" :options="treeData" :props="props" separator="-">

  </el-cascader>
</template>
<script>
import { getDepartment } from '@/api/department';
import { transListToTreeData } from '@/utils';
export default {
  data() {
    return {
        treeData:[],//赋值给级联组件的options
        props:{
            label:'name',//要展示的字段
            value:'id' //要存储的字段
        }
    }
  },
  created(){
    this.getDepartment()
  },
  methods: {
    async getDepartment(){
        this.treeData = transListToTreeData(await getDepartment(),0) //将组织架构的数据 转化树形赋值给treeData
    }
  }
}
</script>

<style scoped lang="scss">
    .el-cascader{
        width: 300px;
    }
</style>
  • 使用组件(src/views/employee/detail.vue)
 <el-form-item prop="departmentId" label="部门" >
                            <!-- 级联部门组件 -->
                            <selectTree v-model="userInfo.departmentId" />
                        </el-form-item>
import selectTree from './components/selectTree.vue'
components:{
    selectTree
  }

9.员工详情-级联组件-双向绑定

在这里插入图片描述

  • 接收value属性(src/views/employee/components/select-tree.vue)
 <el-cascader
    :value="value"
    size="mini"
    :options="treeData"
    :props="props"
    separator="-"
    @change="changeValue"
  />
export default{
  props:{
    value:{
      type:Number,
      default:null 
    }
   },
   data() {
    return {
      treeData: [],//赋值给级联组件的options
      props: {
        label: 'name',//要展示的字段
        value: 'id' //要存储的字段
       
      },
    }
  },
    created() {
    this.getDepartment()
  },
  methods: {
    async getDepartment() {
      this.treeData = transListToTreeData(await getDepartment(), 0) //将组织架构的数据 转化树形赋值给treeData
    },
    changeValue(list) {
      //取到数组的最后一项
      if (list.length > 0) {
        this.$emit('input', list[list.length - 1]) //将最后一位的id取出 传出去
      } else {
        this.$emit('input', null)//如果长度为0 说明值为空
      }
    }
  }
}
  • 级联改变触发input事件(src/views/employee/components/select-tree.vue)
changeValue(list){
  //取到数组的最后一项
  if(list.length > 0){
    this.$emit('input',list[list.length -1]) 
  }else{
    this.$emit('input',null) // 如果长度为0 说明值为空 
  }
}

10.保存更新

在这里插入图片描述

  • 保存更新-新增员工接口-位置(src/api/employee.js)
export function addEmployee(data){
  return request({
    url:'/sys/user',
    methods:'post',
    data 
  })
}
  • 点击保存按钮进行新增-代码位置(src/views/employee/detail.vue)
saveData(){
  this.$refs.userForm.validate(isOK=>{
    if(isOK){
	  //校验通过
	  await addEmployee(this.userInfo)
	  this.$message.success('新增成功');
	  this.$router.push('/employee')
	}
  })
}

11.员工详情-编辑员工-查看员工

在这里插入图片描述
在这里插入图片描述

  • 获取员工详情接口(src/api/employee.js)
export function getEmployeeDetail(id){
  return request({
     url:`/sys/user/${id}`
   })
}
  • 点击查看时跳转到详情携带id(src/views/employee/index.vue)
 <el-button size="mini" @click="$router.push(`/employee/detail/${row.id}`)" type="text">查看</el-button>
  • 配置详情的路由支持新增模式和编辑模式(src/router/modules/employee.js)
  • ?标识可有可无,可以传id也可以不传,页面都能正确显式
{
  path:'/employee/detail/:id?',//
  component:()=>import('@/views/employee/detail.vue'),
  hidden:true,
  meta:{
    title:'员工详情'  
  }
}
  • 员工详情判断是否有id,有id就查询详情数据(src/views/employee/detail.vue)
created(){
  //获取路由参数中的id
  this.$route.params.id && this.getEmployeeDetail()
},
methods:{
  async getEmployeeDetail(){
    this.userInfo = await  getEmployeeDetail(this.$route.params.id)
  }
}

12.员工详情-编辑员工-保存

在这里插入图片描述

  • 更新员工的接口(src/api/employee.js)
 //更新员工
 export function updateEmployee(data){
    return request({
        url:`/sys/user/${data.id}`,
        method:'put',
        data
    })
 }
  • 保存时区分保存和新增(src/views/employee/detail.vue)
 saveData(){
        this.$refs.userForm.validate(async isOK=>{
            if(isOK){
                //编辑模式
                if(this.$route.params.id){
                    await updateEmployee(this.userInfo)
                    this.$message.success('更新成功')
                }else{
                      //校验通过
                    await addEmployee(this.userInfo)
                    this.$message.success('新增员工成功')
                }
              
               this.$router.push('/employee')
            }
        })
    },
  • 当编辑模式时,让手机号不可编辑(src/views/employee/detail.vue)
 <el-input
        v-model="userInfo.mobile"
        :disabled="!!$route.params.id"
        size="mini"
        class="inputW"
  />
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值