1.效果图
2.完整personSelection.vue组件代码
<template>
<div>
<div v-if="editVisible" class="divGjun">
<div class="divGjunIn">
<el-tag
v-for="perSelector in personSelect"
:key="perSelector.userId"
size="mini"
type="info"
>
{{ perSelector.nickName }}
</el-tag>
<div v-show="!personSelect.length > 0">
<el-row>
<el-col :span="20">
<span style="color: #c0c4cc">请选择人员</span>
</el-col>
</el-row>
</div>
</div>
</div>
<div v-else class="divGjunShow" @click="openPerSelector">
<div class="divGjunInShow">
<el-tag
v-for="perSelector in personSelect"
:key="perSelector.userId"
size="mini"
type="info"
>
{{ perSelector.nickName }}
</el-tag>
<div v-show="!personSelect.length > 0">
<el-row>
<el-col :span="20">
<span style="color: #c0c4cc">请选择人员</span>
</el-col>
</el-row>
</div>
</div>
</div>
<el-dialog
:title="title"
:visible.sync="open"
:before-close="handleCancel"
width="70%"
:append-to-body="true"
>
<div>
<el-row>
<el-col :span="6">
<el-input
v-model="organizationQuery.name"
placeholder="请输入组织名称"
clearable
:validate-event="false"
class="input-with-select"
size="mini"
@input="orgFilter"
@keyup.enter.native="orgFilter"
>
<el-button
slot="append"
icon="el-icon-search"
@click="orgFilter"
/>
</el-input>
<el-tree
ref="tree"
v-loading="orgLoading"
class="el-table-high"
:data="orgTree"
:props="defaultProps"
:default-expand-all="true"
:expand-on-click-node="false"
:draggable="false"
:highlight-current="true"
:filter-node-method="filterNode"
:current-node-key="currentKey"
node-key="id"
@node-click="handleNodeClick"
/>
</el-col>
<el-col :span="13" style="margin-left: 8px;">
<el-row>
<el-col :span="24" align="right">
<el-input
v-model="tableQuery.username"
placeholder="请输入姓名"
size="mini"
class="filter-item"
clearable
:validate-event="false"
@input="queryDataSelect"
>
<i
slot="suffix"
style="cursor: pointer"
class="el-input__icon el-icon-search"
@click="queryDataSelect"
/>
</el-input>
</el-col>
</el-row>
<el-row>
<el-table
ref="multipleTable"
v-loading="listLoading"
class="el-table-high"
:data="tableData"
style="width: 100%"
size="mini"
row-key="userId"
:header-cell-style="headerCellStyle"
@selection-change="handleSelect"
@row-click="rowClick"
:header-cell-class-name="cellClass"
:select-all="false"
>
<el-table-column
align="center"
type="selection"
width="50px"
:reserve-selection="true"
/>
<el-table-column
align="center"
prop="nickName"
label="人员姓名"
/>
<el-table-column align="center" prop="phone" label="手机号码" />
</el-table>
<pagination
v-show="tableQuery.total > 0"
:total="tableQuery.total"
:page.sync="tableQuery.pageIndex"
:limit.sync="tableQuery.pageSize"
@pagination="queryData"
/>
</el-row>
</el-col>
<el-col :span="4">
<el-row>
<el-col :span="12">
<div class="selectText">
已选人员(<span style="color: #0080ff">{{
selectList.length
}}</span
>)
</div>
</el-col>
<el-col :span="12" align="right">
<el-button
type="text"
size="mini"
class="delAll"
@click="delAll"
>清空</el-button
>
</el-col>
</el-row>
<el-row>
<ul class="el-table-high">
<li
v-for="(item, index) in selectList"
:key="index"
style="list-style-type: none"
>
<el-row>
<div class="selectLi">
<el-col :span="8">
<div>{{ item.nickName }}</div>
</el-col>
<el-col :span="12">
<div>{{ item.phone }}</div>
</el-col>
<el-col :span="4" align="right">
<el-button type="text" size="small" @click="handleDelSelect(item)"><i class="el-icon-delete" />
</el-button>
</el-col>
</div>
</el-row>
</li>
</ul>
</el-row>
</el-col>
</el-row>
</div>
<div align="right" class="tree_btn">
<el-button type="primary" size="mini" @click="saveOk">确 定</el-button>
<el-button size="mini" @click="handleCancel">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { treeselect } from "@/api/admin/sys-dept";
import { listUser } from "@/api/admin/sys-user";
import _ from "lodash";
export default {
name: "personSelections",
components: {},
props: {
// 已选人员数组
perSelectorList: {
type: Array,
default: () => [],
},
// 是否可编辑
editVisible: {
type: Boolean,
default: false,
},
isMultiple: {
type: Boolean,
default: true,
},
},
data() {
return {
headerCellStyle: {
backgroundColor: "#FAFAFA",
},
orgLoading: true,
listLoading: true,
title: "选择人员",
// 已选员工列表
selectList: [],
// 组织查询
organizationQuery: {},
// 组织树配置选项
defaultProps: {
children: "children",
label: "label",
},
// defaultProps: {
// id: "id",
// children: "children",
// label: "name",
// },
orgTree: [],
// 组织树当前选中
currentKey: "",
// 部门人员列表
tableQuery: {
username: null,
orgId: null,
deptId: null,
pageIndex: 1,
pageSize: 10,
total: 0,
},
// 人员列表
tableData: [],
// 是否显示弹出层
open: false,
personSelect:[]
};
},
watch: {
perSelectorList: {
deep: true,
immediate: true,
handler(v) {
this.personSelect = v;
console.log("this.personSelect", this.personSelect);
}
}
},
created() {},
methods: {
// 打开部门人员加载数据
openPerSelector() {
// 每次打开清空部门/人员搜索
this.orgQuery = {};
this.tableQuery.username = null;
this.tableQuery.pageIndex = 1;
this.initOrgTree();
this.open = true;
// 初始化已选人员列表,根据已选人员列表设置人员列表选中状态(初始化加载)
this.$nextTick(() => {
for (var j = 0; j < this.personSelect.length; j++) {
this.$refs.multipleTable.toggleRowSelection(
this.personSelect[j],
true
);
console.log("this.personSelect[j]", this.personSelect[j]);
}
});
},
// 初始化部门树
initOrgTree() {
this.orgLoading = true;
this.listLoading = true;
treeselect().then((res) => {
this.orgTree = res.data;
this.currentKey = res.data[0].id;
console.log(res.data[0]);
this.$nextTick(() => {
this.$refs.tree.setCurrentKey(this.currentKey);
});
this.tableQuery.deptId = "/" + res.data[0].id + "/";
this.queryData();
this.orgLoading = false;
});
},
// 对树节点进行筛选时执行的方法
filterNode(value, data) {
if (!value) return true;
// return data.name.indexOf(value) !== -1;
return data.label.indexOf(value) !== -1;
},
// 树节点被点击时的回调
handleNodeClick(data) {
this.tableQuery.deptId = "/" + data.id + "/";
this.queryDataSelect();
},
// 组织查询按钮
orgFilter() {
this.$nextTick(() => {
this.$refs.tree.filter(this.organizationQuery.name);
});
},
// 查询人员列表
queryData() {
this.tableQuery.unfinished = false;
this.debouncedGetTableList();
},
queryDataSelect() {
this.tableQuery.pageIndex = 1;
this.debouncedGetTableList();
},
debouncedGetTableList: _.debounce(function () {
this.getTableList();
}, 500),
getTableList() {
this.listLoading = true;
this.paginationLoading = true;
listUser(this.tableQuery).then((res) => {
this.tableData = res.data.list;
this.tableQuery.total = Number(res.data.count);
this.listLoading = false;
});
},
//全选按钮禁用
cellClass(row) {
if (this.isMultiple == false && row.columnIndex === 0) {
return 'all-disabled'
}
},
// 人员列表多选(单选)
handleSelect(val) {
if (this.isMultiple == false) {
this.selectList = val;
if (val.length > 1) {
this.$refs.multipleTable.clearSelection();
this.$refs.multipleTable.toggleRowSelection(val.pop());
}
} else {
this.selectList = val;
}
},
// 人员列表行事件
rowClick(val) {
this.$nextTick(() => {
this.$refs.multipleTable.toggleRowSelection(val);
});
},
// 选择员工删除
handleDelSelect(data) {
this.$nextTick(() => {
this.$refs.multipleTable.toggleRowSelection(data, true);
this.$refs.multipleTable.toggleRowSelection(data, false);
});
},
// 取消
handleCancel() {
this.$emit("handleCancel", false);
this.selectList = [];
// 清空人员列表选中状态
this.$nextTick(() => {
this.$refs.multipleTable.clearSelection();
});
this.open = false;
},
// 清空已选员工
delAll() {
this.selectList = [];
// 清空人员列表选中状态
this.$nextTick(() => {
this.$refs.multipleTable.clearSelection();
});
},
saveOk() {
this.$emit("handleSelectList", this.selectList);
// this.perSelectorList=this.selectList
this.handleCancel();
},
},
};
</script>
<style lang="scss" scoped>
::v-deep .all-disabled .el-checkbox__input .el-checkbox__inner {
background-color: #edf2fc;
border-color: #dcdfe6;
cursor: not-allowed;
}
.divGjun {
border: 1px solid #e4e7ed;
border-radius: 5px;
background-color: #f5f7fa;
color: #c0c4cc;
}
.divGjunIn {
padding-right: 15px;
padding-left: 15px;
background-color: #f5f7fa;
color: #c0c4cc;
}
.divGjunShow {
border: 1px solid #e4e7ed;
border-radius: 5px;
}
.divGjunInShow {
padding-right: 15px;
padding-left: 15px;
}
.selectText {
text-align: center;
height: 28px;
line-height: 28px;
font-size: 12px;
}
.selectLi {
height: 28px;
line-height: 28px;
font-size: 12px;
}
.el-table-high {
height: 56.1vh;
overflow: auto;
}
</style>
3.pagination.vue分页组件
<template>
<div :class="{'hidden':hidden}" class="pagination-container">
<slot name="left"></slot>
<el-pagination
:background="background"
:current-page.sync="currentPage"
:page-size.sync="pageSize"
:layout="layout"
:page-sizes="pageSizes"
:total="total"
v-bind="$attrs"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</template>
<script>
import { scrollTo } from '@/utils/scroll-to'
export default {
name: 'Pagination',
props: {
total: {
required: true,
type: Number
},
page: {
type: Number,
default: 1
},
limit: {
type: Number,
default: 20
},
pageSizes: {
type: Array,
default() {
return [10, 20, 30, 50,100]
}
},
layout: {
type: String,
default: 'total, sizes, prev, pager, next, jumper'
},
background: {
type: Boolean,
default: true
},
autoScroll: {
type: Boolean,
default: true
},
hidden: {
type: Boolean,
default: false
}
},
computed: {
currentPage: {
get() {
return this.page
},
set(val) {
this.$emit('update:page', val)
}
},
pageSize: {
get() {
return this.limit
},
set(val) {
this.$emit('update:limit', val)
}
}
},
methods: {
handleSizeChange(val) {
this.$emit('pagination', { page: this.currentPage, limit: val })
if (this.autoScroll) {
scrollTo(0, 800)
}
},
handleCurrentChange(val) {
this.$emit('pagination', { page: val, limit: this.pageSize })
if (this.autoScroll) {
scrollTo(0, 800)
}
}
}
}
</script>
<style scoped>
.pagination-container {
display: flex;
background: #fff;
padding: 32px 16px;
}
.pagination-container.hidden {
display: none;
}
</style>
4.页面中使用
<el-form-item label="请选择人员" prop="name">
<personSelection
:per-selector-list="form.personList"
:edit-visible="editVisible"
@handleConfirm="selectList"
:isMultiple="false"
></personSelection>
</el-form-item>
editVisible: false,
// 人员选择后
selectList(e) {
this.form.personList = e;
},