页面结构
![](https://img-blog.csdnimg.cn/img_convert/d6a93af43471615b2db5d18d452feeb1.png)
<template>
<div class="container">
<div class="app-container">
<div class="left">
<el-input style="margin-bottom:10px" type="text" prefix-icon="el-icon-search" size="small" placeholder="输入员工姓名全员搜索" />
<!-- 树形组件 -->
</div>
<div class="right">
<el-row class="opeate-tools" type="flex" justify="end">
<el-button size="mini" type="primary">添加员工</el-button>
<el-button size="mini">excel导入</el-button>
<el-button size="mini">excel导出</el-button>
</el-row>
<!-- 表格组件 -->
<!-- 分页 -->
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Employee'
}
</script>
<style lang="scss" scoped>
.app-container {
background: #fff;
display: flex;
.left {
width: 280px;
padding: 20px;
border-right: 1px solid #eaeef4;
}
.right {
flex: 1;
padding: 20px;
.opeate-tools {
margin:10px ;
}
.username {
height: 30px;
width: 30px;
line-height: 30px;
text-align: center;
border-radius: 50%;
color: #fff;
background: #04C9BE;
font-size: 12px;
display:inline-block;
}
}
}
</style>
左树加载
![](https://img-blog.csdnimg.cn/img_convert/0eceb884ed6bd2d1dcdcfec827924aa9.png)
//放置树形组件
<el-tree
:data="depts"
:props="defaultProps"
default-expand-all
:expand-on-click-node="false"
highlight-current
/>
//定义树组件需要的数据
data() {
return {
depts: [], // 组织数据
defaultProps: {
label: 'name',
children: 'children'
}
}
}
//初始化时加载数据转化树形
created() {
this.getDepartment()
},
methods: {
async getDepartment() {
// 递归方法 将列表转化成树形
// let result = await getDepartment()
this.depts = transListToTreeData(await getDepartment(), 0)
}
}
选中首个节点
![](https://img-blog.csdnimg.cn/img_convert/2c53f33057a88201296dbb3c302c1c98.png)
<!-- 树形组件 -->
<!-- 数据、树形配置 -->
<!-- node-key标识唯一性 -->
<el-tree
ref="deptTree"
node-key="id"
:data="depts"
:props="defaultProps"
:default-expand-all="true"
:expand-on-click-node="false"
:highlight-current="true"
@current-change="selectNode"
/>
// 存储查询参数
queryParams: {
departmentId: null
}
async getDepartment () {
// 递归方法 将列表转化成树形
this.depts = transListToTreeData(await getDepartment(), 0)
// 获取首个节点并记录
this.queryParams.departmentId = this.depts[0].id
// 设置选中节点
// 数组件渲染是异步是,等到更新完毕
this.$nextTick(() => {
// 此时意味着数渲染完毕
this.$refs.deptTree.setCurrentKey(this.queryParams.departmentId)
})
},
// 切换节点
selectNode (node) {
console.log(node)
this.queryParams.departmentId = node.id
}
员工列表结构
![](https://img-blog.csdnimg.cn/img_convert/ed03f9a9456e2e639f5788ae998db38e.png)
<!-- 表格组件 -->
<el-table>
<el-table-column align="center" label="头像" />
<el-table-column label="姓名" />
<el-table-column label="手机号" sortable />
<el-table-column label="工号" sortable />
<el-table-column label="聘用形式" />
<el-table-column label="部门" />
<el-table-column label="入职时间" sortable />
<el-table-column label="操作" width="280px">
<template>
<el-button size="mini" type="text">查看</el-button>
<el-button size="mini" type="text">角色</el-button>
<el-button size="mini" type="text">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-row style="height: 60px" align="middle" type="flex" justify="end">
<el-pagination layout="total,prev, pager, next" :total="1000" />
</el-row>
获取员工数据
![](https://img-blog.csdnimg.cn/img_convert/6d160854ac9b7994ce8f7619b06dc855.png)
![](https://img-blog.csdnimg.cn/img_convert/bb1d382a1a88095b19898e9435dc74ae.png)
/**
*
* 获取员工列表
*
*/
export function getEmployeeList (params) {
return request({
url: '/sys/user',
method: 'GET',
params // 地址参数 查询参数
})
}
<!-- 表格组件 -->
<el-table :data="list">
<el-table-column prop="staffPhoto" align="center" label="头像" />
<el-table-column prop="username" label="姓名" />
<el-table-column prop="mobile" label="手机号" sortable />
<el-table-column prop="workNumber" label="工号" sortable />
<el-table-column prop="formOfEmployment" label="聘用形式" />
<el-table-column prop="departmentName" label="部门" />
<el-table-column prop="timeOfEntry" label="入职时间" sortable />
<el-table-column label="操作" width="280px">
<template>
<el-button size="mini" type="text">查看</el-button>
<el-button size="mini" type="text">角色</el-button>
<el-button size="mini" type="text">删除</el-button>
</template>
</el-table-column>
</el-table>
list: [], // 存储员工列表数据
// 获取员工列表的方法
async getEmployeeList () {
const { rows, total } = await getEmployeeList(this.queryParams)
this.list = rows
this.total = total
},
async getDepartment () {
// 递归方法 将列表转化成树形
this.depts = transListToTreeData(await getDepartment(), 0)
// 获取首个节点并记录
this.queryParams.departmentId = this.depts[0].id
// 设置选中节点
// 数组件渲染是异步是,等到更新完毕
this.$nextTick(() => {
// 此时意味着数渲染完毕
this.$refs.deptTree.setCurrentKey(this.queryParams.departmentId)
})
// 这个时候参数记录了id
this.getEmployeeList()
},
// 切换节点
selectNode (node) {
this.queryParams.departmentId = node.id
this.queryParams.page = 1 // 设置为第一页
this.getEmployeeList()
},
头像和聘用形式的处理
![](https://img-blog.csdnimg.cn/img_convert/54f2c48c46a4b41417c2a307bbbe3895.png)
<el-table-column prop="staffPhoto" align="center" label="头像">
<template v-slot="{ row }">
<el-avatar
v-if="row.staffPhoto"
:src="row.staffPhoto"
:size="30"
/>
<span v-else class="username">{{ row.username.charAt(0) }}</span>
</template>
</el-table-column>
<el-table-column prop="formOfEmployment" label="聘用形式">
<template v-slot="{ row }">
<span v-if="row.formOfEmployment === 1">正式</span>
<span v-else-if="row.formOfEmployment === 2">非正式</span>
<span v-else>无</span>
</template>
</el-table-column>
员工分页处理
![](https://img-blog.csdnimg.cn/img_convert/460f9981b1157030e1dde7a7188f20c4.png)
// 存储查询参数
queryParams: {
departmentId: null,
page: 1, // 当前页码
pagesize: 5, // 每页显示的条数
},
total: 0 // 记录员工的总数
<!-- 分页 -->
<el-row style="height: 60px" align="middle" type="flex" justify="end">
<el-pagination
layout="total,prev, pager, next"
:total="total"
:current-page="queryParams.page"
:page-size="queryParams.pagesize"
@current-change="changePage"
/>
</el-row>
// 切换页码
changePage (newPage) {
this.queryParams.page = newPage // 赋值新页码
this.getEmployeeList()
}
// 切换节点
selectNode (node) {
this.queryParams.departmentId = node.id
this.queryParams.page = 1 // 设置为第一页
this.getEmployeeList()
}
// set ElementUI lang to EN
// Vue.use(ElementUI, { locale })
// 如果想要中文版 element-ui,按如下方式声明
Vue.use(ElementUI)
员工模糊搜索
![](https://img-blog.csdnimg.cn/img_convert/43b5f8a32934b5ccc04c3f92a1d139c9.png)
<el-input
v-model="queryParams.keyword"
style="margin-bottom: 10px"
type="text"
prefix-icon="el-icon-search"
size="small"
placeholder="输入员工姓名全员搜索"
@input="changeValue"
/>
// 存储查询参数
queryParams: {
departmentId: null,
page: 1, // 当前页码
pagesize: 5, // 每页显示的条数
keyword: ''
}
// 输入值内容改变时触发
changeValue () {
// 使用防抖节约资源
clearTimeout(this.timer)
// 页码设置第一页
this.timer = setTimeout(() => {
this.queryParams.page = 1
// 查询员工
this.getEmployeeList()
}, 300)
}
员工导出excel
![](https://img-blog.csdnimg.cn/img_convert/8849e8b0e506d2fd79ebf8dff5f3e829.png)
/**
*
* 导出员工的excel
*
*/
export function exportEmployee () {
return request({
url: '/sys/user/export',
// method: 'GET',
// 改变接收数据的类型
responseType: 'blob' // 使用blob接收二进制文件流
})
}
// 判断是不是Blob
if (response.data instanceof Blob) return response.data // 返回了Blob对象
import FileSaver from 'file-saver'
<el-button size="mini" @click="exportEmployee">excel导入</el-button>
// 导出员工的excel
async exportEmployee () {
// await exportEmployee()导出所有的员工接口
// 使用npm包(file-saver),直接将blob文件下载到本地
// FileSaver.saveAs(blob对象,文件名称)
FileSaver.saveAs(await exportEmployee(), '员工信息表.xlsx') // 下载文件
}
excel组件封装
![](https://img-blog.csdnimg.cn/img_convert/ab9ef0d5984d975f0610b0237de441d1.png)
<template>
<el-dialog
width="500px"
title="员工导入"
:visible="showExcelDialog"
@close="$emit('update:showExcelDialog', false)"
>
<el-row type="flex" justify="center">
<div class="upload-excel">
<input
ref="excel-upload-input"
class="excel-upload-input"
type="file"
accept=".xlsx, .xls"
/>
<div class="drop">
<i class="el-icon-upload" />
<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', false)"
>取消</el-button
>
</el-row>
</el-dialog>
</template>
<script>
export default {
props: {
showExcelDialog: {
type: Boolean,
default: false
}
},
methods: {}
}
</script>
<style scoped lang="scss">
.upload-excel {
display: flex;
justify-content: center;
margin: 20px;
width: 360px;
height: 180px;
align-items: center;
color: #697086;
.excel-upload-input {
display: none;
z-index: -9999;
}
.btn-upload,
.drop {
border: 1px dashed #dcdfe6;
width: 100%;
height: 100%;
text-align: center;
line-height: 160px;
border-radius: 8px;
display: flex;
flex-direction: column;
justify-content: center;
}
.drop {
line-height: 40px;
color: #bbb;
i {
font-size: 60px;
display: block;
color: #c0c4cc;
}
}
}
</style>
<el-button size="mini" @click="importEmployee">excel导入</el-button>
<!-- 放置导入组件 -->
<import-excel :show-excel-dialog.sync="showExcelDialog" />
components: {1
ImportExcel
},
// 导入员工的excel
importEmployee () {
this.showExcelDialog = true
}
excel-下载导入模板
![](https://img-blog.csdnimg.cn/img_convert/81b279082896219ee613e29d9d8148b2.png)
/**
*
* 下载导入员工模板
*
*/
export function getExportTemplate () {
return request({
url: '/sys/user/import/template',
method: 'GET',
// 改变接收数据的类型
responseType: 'blob' // 使用blob接收二进制文件流
})
}
<el-button type="text" @click="getTemplate">下载导入模板</el-button>
async getTemplate () {
FileSaver.saveAs(await getExportTemplate(), '员工导入模板.xlsx')
}
员工导入-上传excel
![](https://img-blog.csdnimg.cn/img_convert/ae7690bf8c7b98b6786753fc51140ae3.png)
/**
*
* 导入员工(上传excel)
*
*/
export function uploadExcel (data) {
return request({
url: '/sys/user/import',
method: 'POST',
data // form-data类型 因为要上传文件类型
})
}
<el-button type="text" @click="handleUpload">点击上传</el-button>
<input
ref="excel-upload-input"
class="excel-upload-input"
type="file"
accept=".xlsx, .xls"
@change="uploadChange"
/>
// 弹出文件选择器-只有一种方式,通过input file
handleUpload () {
this.$refs['excel-upload-input'].click()
},
async uploadChange (event) {
// input文件列表
const files = event.target.files
if (files.length > 0) {
// 大于0,说明有文件要上传
const data = new FormData()
// file: file类型
data.append('file', files[0]) // 将文件参数加入到formData中
try {
await uploadExcel(data)
// 成功
this.$emit('uploadSucess') // 通知父组件 我上传成功
this.$emit('update:showExcelDialog', false)
this.$message.success('上传文件成功')
} catch (error) {
// 捕获失败
} finally {
this.$refs['excel-upload-input'].value = ''
}
}
}
<!-- 放置导入excel组件 -->
<import-excel
:show-excel-dialog.sync="showExcelDialog"
@uploadSuccess="getEmployeeList"
/>
删除员工
![](https://img-blog.csdnimg.cn/img_convert/f9316ac5a27f4fc2592eabbb9955c2dd.png)
/**
*
* 删除-员工
*
*/
export function delEmployee (id) {
// request执行之后会得到promise对象(再通过使用async和await可以获取结果)
return request({
url: `/sys/user/${id}`,
method: 'DELETE'
})
}
<el-popconfirm
title="确认删除该行数据吗?"
@onConfirm="confirmDel(row.id)"
>
<el-button
slot="reference"
style="margin-left: 10px"
type="text"
>删除</el-button
>
</el-popconfirm>
async confirmDel (id) {
await delEmployee(id)
// 如果是当页最后一个
if (this.list.length === 1 && this.queryParams.page > 1) {
this.queryParams.page--
}
// 重新加载
this.getEmployeeList()
this.$message.success('删除员工成功')
}