|
@@ -24,16 +24,20 @@
|
|
|
</div>
|
|
</div>
|
|
|
<!-- 表格 -->
|
|
<!-- 表格 -->
|
|
|
<template v-slot:content>
|
|
<template v-slot:content>
|
|
|
- <user-select-search @search="reload"></user-select-search>
|
|
|
|
|
|
|
+ <user-select-search
|
|
|
|
|
+ ref="search"
|
|
|
|
|
+ @search="reload"
|
|
|
|
|
+ ></user-select-search>
|
|
|
<ele-pro-table
|
|
<ele-pro-table
|
|
|
ref="table"
|
|
ref="table"
|
|
|
:columns="currentColumns"
|
|
:columns="currentColumns"
|
|
|
:datasource="datasource"
|
|
:datasource="datasource"
|
|
|
row-key="id"
|
|
row-key="id"
|
|
|
- height="calc(100vh - 430px)"
|
|
|
|
|
|
|
+ :height="tableHeight"
|
|
|
class="dict-table"
|
|
class="dict-table"
|
|
|
@cell-click="cellClick"
|
|
@cell-click="cellClick"
|
|
|
@selection-change="handleSelectionChange"
|
|
@selection-change="handleSelectionChange"
|
|
|
|
|
+ @done="handleTableDone"
|
|
|
>
|
|
>
|
|
|
<!-- 表头工具栏 -->
|
|
<!-- 表头工具栏 -->
|
|
|
<template v-slot:action="{ row }" v-if="!isMultiple">
|
|
<template v-slot:action="{ row }" v-if="!isMultiple">
|
|
@@ -47,6 +51,9 @@
|
|
|
</el-card>
|
|
</el-card>
|
|
|
|
|
|
|
|
<div slot="footer" class="dialog-footer">
|
|
<div slot="footer" class="dialog-footer">
|
|
|
|
|
+ <span v-if="isMultiple" class="selected-count"
|
|
|
|
|
+ >已选 {{ selectedCount }} 人</span
|
|
|
|
|
+ >
|
|
|
<el-button type="primary" size="small" @click="selected">选择</el-button>
|
|
<el-button type="primary" size="small" @click="selected">选择</el-button>
|
|
|
<el-button size="small" @click="handleClose">关闭</el-button>
|
|
<el-button size="small" @click="handleClose">关闭</el-button>
|
|
|
</div>
|
|
</div>
|
|
@@ -67,6 +74,13 @@
|
|
|
default: () => {
|
|
default: () => {
|
|
|
return [];
|
|
return [];
|
|
|
}
|
|
}
|
|
|
|
|
+ },
|
|
|
|
|
+ // 已选人员(打开时回显,确定后与本次勾选合并返回)
|
|
|
|
|
+ selectedList: {
|
|
|
|
|
+ type: Array,
|
|
|
|
|
+ default: () => {
|
|
|
|
|
+ return [];
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
data() {
|
|
data() {
|
|
@@ -76,6 +90,12 @@
|
|
|
visible: false,
|
|
visible: false,
|
|
|
isMultiple: false,
|
|
isMultiple: false,
|
|
|
selectedRows: [],
|
|
selectedRows: [],
|
|
|
|
|
+ // 本次打开时已选人员(在表格中选择框中勾选回显)
|
|
|
|
|
+ preselected: [],
|
|
|
|
|
+ // 本次打开后被取消勾选的已选人员 id
|
|
|
|
|
+ uncheckedIds: [],
|
|
|
|
|
+ // 当前选中的部门节点
|
|
|
|
|
+ curNodeData: null,
|
|
|
current: null,
|
|
current: null,
|
|
|
statusOptions: [
|
|
statusOptions: [
|
|
|
{ value: 1, label: '全职' },
|
|
{ value: 1, label: '全职' },
|
|
@@ -152,11 +172,21 @@
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
computed: {
|
|
computed: {
|
|
|
|
|
+ // 表格高度
|
|
|
|
|
+ tableHeight() {
|
|
|
|
|
+ return 'calc(100vh - 430px)';
|
|
|
|
|
+ },
|
|
|
|
|
+ // 已选人数
|
|
|
|
|
+ selectedCount() {
|
|
|
|
|
+ return this.mergeSelected().length;
|
|
|
|
|
+ },
|
|
|
currentColumns() {
|
|
currentColumns() {
|
|
|
if (this.isMultiple) {
|
|
if (this.isMultiple) {
|
|
|
return [
|
|
return [
|
|
|
{
|
|
{
|
|
|
type: 'selection',
|
|
type: 'selection',
|
|
|
|
|
+ // 跨页/重新加载后保留勾选状态,配合 row-key 使用
|
|
|
|
|
+ reserveSelection: true,
|
|
|
width: 55,
|
|
width: 55,
|
|
|
align: 'center',
|
|
align: 'center',
|
|
|
selectable: (row, index) => {
|
|
selectable: (row, index) => {
|
|
@@ -177,8 +207,19 @@
|
|
|
open(item, index = 0, multiple = false) {
|
|
open(item, index = 0, multiple = false) {
|
|
|
this.isMultiple = multiple;
|
|
this.isMultiple = multiple;
|
|
|
this.selectedRows = [];
|
|
this.selectedRows = [];
|
|
|
|
|
+ this.uncheckedIds = [];
|
|
|
|
|
+ this.current = null;
|
|
|
|
|
+ this.radio = null;
|
|
|
|
|
+ // 已选人员回显(打开时在表格的选择框中勾选)
|
|
|
|
|
+ this.preselected = [...(this.selectedList || [])];
|
|
|
if (item) {
|
|
if (item) {
|
|
|
this.radio = item.id;
|
|
this.radio = item.id;
|
|
|
|
|
+ // 单选时保持原有选中,未重新选择则沿用
|
|
|
|
|
+ this.current = item;
|
|
|
|
|
+ } else if (!multiple && this.preselected.length) {
|
|
|
|
|
+ const first = this.preselected[0];
|
|
|
|
|
+ this.radio = first.id;
|
|
|
|
|
+ this.current = first;
|
|
|
}
|
|
}
|
|
|
this.currentIndex = index;
|
|
this.currentIndex = index;
|
|
|
// 先亮起弹窗再排 nextTick:首次打开时对话框内容尚未挂载,
|
|
// 先亮起弹窗再排 nextTick:首次打开时对话框内容尚未挂载,
|
|
@@ -187,22 +228,120 @@
|
|
|
this.$nextTick(() => {
|
|
this.$nextTick(() => {
|
|
|
if (this.$refs.table) {
|
|
if (this.$refs.table) {
|
|
|
this.$refs.table.clearSelection();
|
|
this.$refs.table.clearSelection();
|
|
|
|
|
+ // 已选人员勾选到表格的选择框中
|
|
|
|
|
+ this.syncPreselectedSelection();
|
|
|
}
|
|
}
|
|
|
|
|
+ // 每次打开重置搜索条件与部门筛选
|
|
|
|
|
+ this.resetFilter();
|
|
|
});
|
|
});
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
|
|
+ /* 重置搜索条件与部门树选中 */
|
|
|
|
|
+ resetFilter() {
|
|
|
|
|
+ this.curNodeData = null;
|
|
|
|
|
+ const tree = this.$refs.treeList && this.$refs.treeList.getInstance();
|
|
|
|
|
+ if (tree) {
|
|
|
|
|
+ tree.setCurrentKey(null);
|
|
|
|
|
+ }
|
|
|
|
|
+ // 每页条数回初始值
|
|
|
|
|
+ const table = this.$refs.table;
|
|
|
|
|
+ if (table) {
|
|
|
|
|
+ const pageSize = table.pageSize || 10;
|
|
|
|
|
+ if (table.tableLimit !== pageSize) {
|
|
|
|
|
+ table.tableLimit = pageSize;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.$refs.search) {
|
|
|
|
|
+ // 清空搜索条件并重新加载表格
|
|
|
|
|
+ this.$refs.search.reset();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.reload();
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ /* 表格数据加载完成:保证已选人员仍处于勾选状态 */
|
|
|
|
|
+ handleTableDone() {
|
|
|
|
|
+ this.syncPreselectedSelection();
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ /* 将已选人员同步为表格中的勾选状态 */
|
|
|
|
|
+ syncPreselectedSelection() {
|
|
|
|
|
+ const table = this.$refs.table;
|
|
|
|
|
+ if (!table || !this.isMultiple) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ const dataMap = new Map();
|
|
|
|
|
+ this.getTableData().forEach((row) => dataMap.set(row.id, row));
|
|
|
|
|
+ const selectedIds = new Set(
|
|
|
|
|
+ (this.selectedRows || []).map((row) => row.id)
|
|
|
|
|
+ );
|
|
|
|
|
+ this.preselected.forEach((item) => {
|
|
|
|
|
+ if (
|
|
|
|
|
+ !item ||
|
|
|
|
|
+ item.id == null ||
|
|
|
|
|
+ selectedIds.has(item.id) ||
|
|
|
|
|
+ // 本次打开后被取消勾选的,不再重新勾选
|
|
|
|
|
+ this.uncheckedIds.includes(item.id)
|
|
|
|
|
+ ) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 优先使用表格中的行对象,保证复选框能正常回显
|
|
|
|
|
+ const row = dataMap.get(item.id) || item;
|
|
|
|
|
+ table.toggleRowSelection(row, true);
|
|
|
|
|
+ selectedIds.add(item.id);
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ /* 表格当前数据 */
|
|
|
|
|
+ getTableData() {
|
|
|
|
|
+ const table = this.$refs.table;
|
|
|
|
|
+ if (table && typeof table.getData === 'function') {
|
|
|
|
|
+ return table.getData() || [];
|
|
|
|
|
+ }
|
|
|
|
|
+ return [];
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ /* 合并已选人员与本次勾选的人员 */
|
|
|
|
|
+ mergeSelected() {
|
|
|
|
|
+ const map = new Map();
|
|
|
|
|
+ const dataMap = new Map(
|
|
|
|
|
+ this.getTableData().map((row) => [row.id, row])
|
|
|
|
|
+ );
|
|
|
|
|
+ // 已选人员(未被取消勾选的)
|
|
|
|
|
+ this.preselected.forEach((item) => {
|
|
|
|
|
+ if (!item || item.id == null || this.uncheckedIds.includes(item.id)) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ map.set(item.id, dataMap.get(item.id) || item);
|
|
|
|
|
+ });
|
|
|
|
|
+ // 本次勾选的人员
|
|
|
|
|
+ (this.selectedRows || []).forEach((row) => {
|
|
|
|
|
+ if (!row || row.id == null) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ map.set(row.id, dataMap.get(row.id) || row);
|
|
|
|
|
+ });
|
|
|
|
|
+ return Array.from(map.values());
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
/* 表格数据源 */
|
|
/* 表格数据源 */
|
|
|
- datasource({ page, limit, where, order }) {
|
|
|
|
|
- return getUserPage({
|
|
|
|
|
|
|
+ datasource({ page, limit, where }) {
|
|
|
|
|
+ const params = {
|
|
|
pageNum: page,
|
|
pageNum: page,
|
|
|
- size: limit,
|
|
|
|
|
- ...where
|
|
|
|
|
|
|
+ size: limit
|
|
|
|
|
+ };
|
|
|
|
|
+ Object.keys(where || {}).forEach((key) => {
|
|
|
|
|
+ const value = where[key];
|
|
|
|
|
+ if (value !== undefined && value !== null && value !== '') {
|
|
|
|
|
+ params[key] = value;
|
|
|
|
|
+ }
|
|
|
});
|
|
});
|
|
|
|
|
+ return getUserPage(params);
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
/* 刷新表格 */
|
|
/* 刷新表格 */
|
|
|
reload(where) {
|
|
reload(where) {
|
|
|
- this.$refs.table.reload({ pageNum: 1, where: where });
|
|
|
|
|
|
|
+ this.$refs.table.reload({ page: 1, where: where });
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
handleNodeClick(data, node) {
|
|
handleNodeClick(data, node) {
|
|
@@ -218,22 +357,36 @@
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
handleSelectionChange(rows) {
|
|
handleSelectionChange(rows) {
|
|
|
- this.selectedRows = rows;
|
|
|
|
|
|
|
+ const list = rows || [];
|
|
|
|
|
+ const prevIds = new Set((this.selectedRows || []).map((row) => row.id));
|
|
|
|
|
+ const curIds = new Set(list.map((row) => row.id));
|
|
|
|
|
+ // 被取消勾选的人员
|
|
|
|
|
+ prevIds.forEach((id) => {
|
|
|
|
|
+ if (!curIds.has(id) && !this.uncheckedIds.includes(id)) {
|
|
|
|
|
+ this.uncheckedIds.push(id);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ // 被重新勾选的人员
|
|
|
|
|
+ this.uncheckedIds = this.uncheckedIds.filter((id) => !curIds.has(id));
|
|
|
|
|
+ this.selectedRows = list;
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
handleClose() {
|
|
handleClose() {
|
|
|
this.visible = false;
|
|
this.visible = false;
|
|
|
this.current = null;
|
|
this.current = null;
|
|
|
- this.radio = '';
|
|
|
|
|
|
|
+ this.radio = null;
|
|
|
this.selectedRows = [];
|
|
this.selectedRows = [];
|
|
|
|
|
+ this.uncheckedIds = [];
|
|
|
|
|
+ this.preselected = [];
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
selected() {
|
|
selected() {
|
|
|
if (this.isMultiple) {
|
|
if (this.isMultiple) {
|
|
|
- if (!this.selectedRows.length) {
|
|
|
|
|
|
|
+ const rows = this.mergeSelected();
|
|
|
|
|
+ if (!rows.length) {
|
|
|
return this.$message.warning('请至少选择一项');
|
|
return this.$message.warning('请至少选择一项');
|
|
|
}
|
|
}
|
|
|
- this.$emit('changeParent', this.selectedRows, this.currentIndex);
|
|
|
|
|
|
|
+ this.$emit('changeParent', rows, this.currentIndex);
|
|
|
} else {
|
|
} else {
|
|
|
if (!this.current) {
|
|
if (!this.current) {
|
|
|
return this.$message.warning('请至少选择一项');
|
|
return this.$message.warning('请至少选择一项');
|
|
@@ -247,6 +400,12 @@
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
<style lang="scss" scoped>
|
|
|
|
|
+ .selected-count {
|
|
|
|
|
+ float: left;
|
|
|
|
|
+ line-height: 32px;
|
|
|
|
|
+ color: #606266;
|
|
|
|
|
+ font-size: 13px;
|
|
|
|
|
+ }
|
|
|
.tree_col {
|
|
.tree_col {
|
|
|
border: 1px solid #eee;
|
|
border: 1px solid #eee;
|
|
|
padding: 10px 0;
|
|
padding: 10px 0;
|