|
|
@@ -1,9 +1,11 @@
|
|
|
<template>
|
|
|
<el-popover
|
|
|
ref="popover"
|
|
|
+ :key="prop"
|
|
|
placement="bottom"
|
|
|
width="340"
|
|
|
trigger="click"
|
|
|
+ :class="{ 'has-filter': hasFilter() }"
|
|
|
@show="onPopoverShow"
|
|
|
>
|
|
|
<!-- 搜索条 -->
|
|
|
@@ -56,12 +58,12 @@
|
|
|
</div>
|
|
|
|
|
|
<!-- 多选列表 -->
|
|
|
- <div v-else class="mb5" style="max-height: 350px; overflow: auto">
|
|
|
+ <div v-else class="mb5">
|
|
|
<el-table
|
|
|
ref="multipleTable"
|
|
|
:data="filteredList"
|
|
|
size="mini"
|
|
|
- height="350"
|
|
|
+ height="250"
|
|
|
@selection-change="handleSelectionChange"
|
|
|
@row-click="handleClickRow"
|
|
|
>
|
|
|
@@ -82,6 +84,21 @@
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
+
|
|
|
+ <!-- 分页 -->
|
|
|
+ <div v-if="total > 0" class="mt5">
|
|
|
+ <el-pagination
|
|
|
+ background
|
|
|
+ layout="total, sizes, prev, pager, next, jumper"
|
|
|
+ :total="total"
|
|
|
+ :page-size.sync="pageSize"
|
|
|
+ :current-page.sync="pageNo"
|
|
|
+ style="min-width: 300px; overflow-x: auto"
|
|
|
+ :page-sizes="[20, 50, 100, 200]"
|
|
|
+ @size-change="handleSizeChange"
|
|
|
+ @current-change="handleCurrentChange"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 按钮 -->
|
|
|
@@ -123,9 +140,14 @@ export default {
|
|
|
searchKey: "",
|
|
|
dateRangeValue: "",
|
|
|
currentRows: [],
|
|
|
+ allSelectedColumns: new Set(), // 保存选中的column值,确保跨分页唯一性
|
|
|
filterData: [],
|
|
|
loading: false,
|
|
|
isFirstLoad: true,
|
|
|
+ // 分页相关
|
|
|
+ pageNo: 1,
|
|
|
+ pageSize: 50,
|
|
|
+ total: 0,
|
|
|
};
|
|
|
},
|
|
|
computed: {
|
|
|
@@ -150,10 +172,23 @@ export default {
|
|
|
}, []);
|
|
|
},
|
|
|
filteredList() {
|
|
|
- if (!this.searchKey.trim()) return this.originalList;
|
|
|
- return this.originalList.filter((item) =>
|
|
|
- String(item.column).toLowerCase().includes(this.searchKey.toLowerCase())
|
|
|
- );
|
|
|
+ // 先进行搜索过滤
|
|
|
+ let filtered = this.originalList;
|
|
|
+ if (this.searchKey.trim()) {
|
|
|
+ filtered = this.originalList.filter((item) =>
|
|
|
+ String(item.column)
|
|
|
+ .toLowerCase()
|
|
|
+ .includes(this.searchKey.toLowerCase())
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新总数
|
|
|
+ this.total = filtered.length;
|
|
|
+
|
|
|
+ // 再进行分页
|
|
|
+ const start = (this.pageNo - 1) * this.pageSize;
|
|
|
+ const end = start + this.pageSize;
|
|
|
+ return filtered.slice(start, end);
|
|
|
},
|
|
|
},
|
|
|
watch: {
|
|
|
@@ -162,8 +197,16 @@ export default {
|
|
|
},
|
|
|
},
|
|
|
methods: {
|
|
|
+ /* ---- 工具方法 ---- */
|
|
|
+ hasFilter() {
|
|
|
+ return !!(
|
|
|
+ this.activeFilters[this.prop] && this.activeFilters[this.prop].length
|
|
|
+ );
|
|
|
+ },
|
|
|
+
|
|
|
/* ---- 生命周期 ---- */
|
|
|
async onPopoverShow() {
|
|
|
+ console.log("onPopoverShow被调用");
|
|
|
this.$nextTick(() => this.$refs.seachRef?.focus());
|
|
|
if (this.isFirstLoad || this.searchKey) {
|
|
|
await this.fetchFilterListInQueryManage(true);
|
|
|
@@ -194,6 +237,10 @@ export default {
|
|
|
|
|
|
/* ---- 数据获取 ---- */
|
|
|
async fetchFilterListInQueryManage(reload) {
|
|
|
+ console.log(
|
|
|
+ "fetchFilterListInQueryManage被调用,htmlType:",
|
|
|
+ this.htmlType
|
|
|
+ );
|
|
|
if (["datetime", "daterange"].includes(this.htmlType)) return;
|
|
|
try {
|
|
|
this.loading = true;
|
|
|
@@ -207,8 +254,10 @@ export default {
|
|
|
params[k] = this.activeFilters[k].map((i) => i.column).join(",");
|
|
|
}
|
|
|
});
|
|
|
+ console.log("调用getFilterListInQuery,参数:", params);
|
|
|
const { data } = await getFilterListInQuery(params);
|
|
|
this.filterData = data || [];
|
|
|
+ console.log("获取筛选数据成功,filterData:", this.filterData);
|
|
|
} catch (error) {
|
|
|
console.error("获取筛选数据失败:", error);
|
|
|
} finally {
|
|
|
@@ -244,11 +293,41 @@ export default {
|
|
|
|
|
|
/* ---- 多选处理 ---- */
|
|
|
handleSelectionChange(selection) {
|
|
|
- this.currentRows = selection;
|
|
|
+ // 获取当前页的所有column值
|
|
|
+ const currentPageColumns = new Set(
|
|
|
+ this.filteredList.map((item) => item.column)
|
|
|
+ );
|
|
|
+
|
|
|
+ // 移除currentRows中当前页已存在的选中数据(避免重复)
|
|
|
+ this.currentRows = this.currentRows.filter(
|
|
|
+ (item) => !currentPageColumns.has(item.column)
|
|
|
+ );
|
|
|
+
|
|
|
+ // 添加当前页新选中的数据
|
|
|
+ this.currentRows.push(...selection);
|
|
|
+
|
|
|
+ // 更新allSelectedColumns集合
|
|
|
+ this.allSelectedColumns.clear();
|
|
|
+ this.currentRows.forEach((item) =>
|
|
|
+ this.allSelectedColumns.add(item.column)
|
|
|
+ );
|
|
|
},
|
|
|
handleClickRow(row) {
|
|
|
- const checked = this.currentRows.some((s) => s.column === row.column);
|
|
|
- this.$refs.multipleTable.toggleRowSelection(row, !checked);
|
|
|
+ const checked = this.allSelectedColumns.has(row.column);
|
|
|
+
|
|
|
+ if (checked) {
|
|
|
+ // 取消选中
|
|
|
+ this.allSelectedColumns.delete(row.column);
|
|
|
+ this.currentRows = this.currentRows.filter(
|
|
|
+ (item) => item.column !== row.column
|
|
|
+ );
|
|
|
+ this.$refs.multipleTable.toggleRowSelection(row, false);
|
|
|
+ } else {
|
|
|
+ // 添加选中
|
|
|
+ this.allSelectedColumns.add(row.column);
|
|
|
+ this.currentRows.push(row);
|
|
|
+ this.$refs.multipleTable.toggleRowSelection(row, true);
|
|
|
+ }
|
|
|
},
|
|
|
toggleSelection(rows) {
|
|
|
const table = this.$refs.multipleTable;
|
|
|
@@ -262,9 +341,12 @@ export default {
|
|
|
const table = this.$refs.multipleTable;
|
|
|
if (!table) return;
|
|
|
table.clearSelection();
|
|
|
- this.currentRows.forEach((r) => {
|
|
|
- const target = this.filteredList.find((i) => i.column === r.column);
|
|
|
- if (target) table.toggleRowSelection(target, true);
|
|
|
+
|
|
|
+ // 根据allSelectedColumns恢复当前页的选中状态
|
|
|
+ this.filteredList.forEach((item) => {
|
|
|
+ if (this.allSelectedColumns.has(item.column)) {
|
|
|
+ table.toggleRowSelection(item, true);
|
|
|
+ }
|
|
|
});
|
|
|
});
|
|
|
},
|
|
|
@@ -281,9 +363,16 @@ export default {
|
|
|
},
|
|
|
|
|
|
/* ---- 按钮 ---- */
|
|
|
+ handleClose() {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ // 把焦点还给搜索图标,防止 aria-hidden 作用在聚焦元素
|
|
|
+ this.$el.closest("th").querySelector(".svg-icon")?.focus();
|
|
|
+ });
|
|
|
+ },
|
|
|
filterConfirm() {
|
|
|
this.$emit("select-data", this.currentRows, this.prop, this.htmlType);
|
|
|
this.$refs.popover.doClose();
|
|
|
+ this.handleClose();
|
|
|
},
|
|
|
filterCancel(flag) {
|
|
|
this.searchKey = "";
|
|
|
@@ -293,11 +382,24 @@ export default {
|
|
|
this.$emit("select-data", [], this.prop, this.htmlType);
|
|
|
this.$refs.popover.doClose();
|
|
|
this.isFirstLoad = true;
|
|
|
+ this.handleClose();
|
|
|
}
|
|
|
},
|
|
|
handleFilterSearch() {
|
|
|
this.fetchFilterListInQueryManage();
|
|
|
},
|
|
|
+
|
|
|
+ /* ---- 分页处理 ---- */
|
|
|
+ handleSizeChange(val) {
|
|
|
+ this.pageSize = val;
|
|
|
+ this.pageNo = 1; // 切换每页条数时重置页码
|
|
|
+ this.restoreSelections(); // 重新恢复选中状态
|
|
|
+ },
|
|
|
+
|
|
|
+ handleCurrentChange(val) {
|
|
|
+ this.pageNo = val;
|
|
|
+ this.restoreSelections(); // 重新恢复选中状态
|
|
|
+ },
|
|
|
},
|
|
|
};
|
|
|
</script>
|