@blueking/vxe-table
Version:
一个基于 vue 的 PC 端表格组件,支持增删改查、虚拟树、列拖拽,懒加载、快捷菜单、数据校验、树形结构、打印、导入导出、自定义模板、渲染器、JSON 配置式...
449 lines (448 loc) • 15.2 kB
JavaScript
"use strict";
var _vue = require("vue");
var _xeUtils = _interopRequireDefault(require("xe-utils"));
var _ui = require("../../../ui");
var _util = require("../../src/util");
var _dom = require("../../../ui/src/dom");
var _utils = require("../../../ui/src/utils");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const {
renderer,
hooks
} = _ui.VxeUI;
const tableFilterMethodKeys = ['openFilter', 'setFilter', 'clearFilter', 'saveFilterPanel', 'resetFilterPanel', 'getCheckedFilters', 'updateFilterOptionStatus'];
hooks.add('tableFilterModule', {
setupTable($xeTable) {
const {
props,
reactData,
internalData
} = $xeTable;
const {
refTableHeader,
refTableBody,
refTableFilter
} = $xeTable.getRefMaps();
const {
computeFilterOpts,
computeMouseOpts
} = $xeTable.getComputeMaps();
// 确认筛选
const handleFilterConfirmFilter = evnt => {
const {
filterStore
} = reactData;
filterStore.options.forEach(option => {
option.checked = option._checked;
});
$xeTable.confirmFilterEvent(evnt);
};
// (单选)筛选发生改变
const changeRadioOption = (evnt, checked, item) => {
const {
filterStore
} = reactData;
filterStore.options.forEach(option => {
option._checked = false;
});
item._checked = checked;
$xeTable.checkFilterOptions();
handleFilterConfirmFilter(evnt);
};
// (多选)筛选发生改变
const changeMultipleOption = (evnt, checked, item) => {
item._checked = checked;
$xeTable.checkFilterOptions();
};
/**
* 重置筛选
* 当筛选面板中的重置按钮被按下时触发
* @param {Event} evnt 事件
*/
const handleFilterResetFilter = evnt => {
const {
filterStore
} = reactData;
$xeTable.handleClearFilter(filterStore.column);
$xeTable.confirmFilterEvent(evnt);
};
const filterPrivateMethods = {
checkFilterOptions() {
const {
filterStore
} = reactData;
filterStore.isAllSelected = filterStore.options.every(item => item._checked);
filterStore.isIndeterminate = !filterStore.isAllSelected && filterStore.options.some(item => item._checked);
},
/**
* 点击筛选事件
* 当筛选图标被点击时触发
* 更新选项是否全部状态
* 打开筛选面板
* @param {Event} evnt 事件
* @param {ColumnInfo} column 列配置
* @param {Object} params 参数
*/
triggerFilterEvent(evnt, column, params) {
const {
initStore,
filterStore
} = reactData;
if (filterStore.column === column && filterStore.visible) {
filterStore.visible = false;
} else {
const {
target: targetElem,
pageX
} = evnt;
const {
visibleWidth
} = (0, _dom.getDomNode)();
const {
filters,
filterMultiple,
filterRender
} = column;
const compConf = (0, _utils.isEnableConf)(filterRender) ? renderer.get(filterRender.name) : null;
const frMethod = column.filterRecoverMethod || (compConf ? compConf.tableFilterRecoverMethod || compConf.filterRecoverMethod : null);
internalData._currFilterParams = params;
Object.assign(filterStore, {
multiple: filterMultiple,
options: filters,
column,
style: null
});
// 复原状态
filterStore.options.forEach(option => {
const {
_checked,
checked
} = option;
option._checked = checked;
if (!checked && _checked !== checked) {
if (frMethod) {
frMethod({
option,
column,
$table: $xeTable
});
}
}
});
this.checkFilterOptions();
filterStore.visible = true;
initStore.filter = true;
(0, _vue.nextTick)(() => {
const tableHeader = refTableHeader.value;
const tableBody = refTableBody.value;
const headerElem = tableHeader ? tableHeader.$el : null;
const bodyElem = tableBody.$el;
if (!bodyElem) {
return;
}
const tableFilter = refTableFilter.value;
const filterWrapperElem = tableFilter ? tableFilter.$el : null;
if (!filterWrapperElem) {
return;
}
const filterWidth = filterWrapperElem.offsetWidth;
const filterHeight = filterWrapperElem.offsetHeight;
const filterHeadElem = filterWrapperElem.querySelector('.vxe-table--filter-header');
const filterFootElem = filterWrapperElem.querySelector('.vxe-table--filter-footer');
const centerWidth = filterWidth / 2;
const minMargin = 10;
const maxLeft = bodyElem.clientWidth - filterWidth - minMargin;
let left, right;
const style = {
top: `${targetElem.offsetTop + targetElem.offsetParent.offsetTop + targetElem.offsetHeight}px`
};
// 判断面板不能大于表格高度
let maxHeight = null;
const bodyHeight = bodyElem.clientHeight - (headerElem ? headerElem.clientHeight / 2 : 0);
if (filterHeight >= bodyHeight) {
maxHeight = Math.max(40, bodyHeight - (filterFootElem ? filterFootElem.offsetHeight : 0) - (filterHeadElem ? filterHeadElem.offsetHeight : 0));
}
if (column.fixed === 'left') {
left = targetElem.offsetLeft + targetElem.offsetParent.offsetLeft - centerWidth;
} else if (column.fixed === 'right') {
right = targetElem.offsetParent.offsetWidth - targetElem.offsetLeft + (targetElem.offsetParent.offsetParent.offsetWidth - targetElem.offsetParent.offsetLeft) - column.renderWidth - centerWidth;
} else {
left = targetElem.offsetLeft + targetElem.offsetParent.offsetLeft - centerWidth - bodyElem.scrollLeft;
}
if (left) {
const overflowWidth = pageX + filterWidth - centerWidth + minMargin - visibleWidth;
if (overflowWidth > 0) {
left -= overflowWidth;
}
style.left = `${Math.min(maxLeft, Math.max(minMargin, left))}px`;
} else if (right) {
const overflowWidth = pageX + filterWidth - centerWidth + minMargin - visibleWidth;
if (overflowWidth > 0) {
right += overflowWidth;
}
style.right = `${Math.max(minMargin, right)}px`;
}
filterStore.style = style;
filterStore.maxHeight = maxHeight;
});
}
$xeTable.dispatchEvent('filter-visible', {
column,
field: column.field,
property: column.field,
filterList: $xeTable.getCheckedFilters(),
visible: filterStore.visible
}, evnt);
},
handleClearFilter(column) {
if (column) {
const {
filters,
filterRender
} = column;
if (filters) {
const compConf = (0, _utils.isEnableConf)(filterRender) ? renderer.get(filterRender.name) : null;
const frMethod = column.filterResetMethod || (compConf ? compConf.tableFilterResetMethod || compConf.filterResetMethod : null);
filters.forEach(item => {
item._checked = false;
item.checked = false;
if (!frMethod) {
item.data = _xeUtils.default.clone(item.resetValue, true);
}
});
if (frMethod) {
frMethod({
options: filters,
column,
$table: $xeTable
});
}
}
}
},
handleColumnConfirmFilter(column, evnt) {
const {
mouseConfig
} = props;
const {
scrollXLoad: oldScrollXLoad,
scrollYLoad: oldScrollYLoad
} = reactData;
const filterOpts = computeFilterOpts.value;
const mouseOpts = computeMouseOpts.value;
const {
field
} = column;
const values = [];
const datas = [];
column.filters.forEach(item => {
if (item.checked) {
values.push(item.value);
datas.push(item.data);
}
});
const filterList = $xeTable.getCheckedFilters();
const params = {
$table: $xeTable,
$event: evnt,
column,
field,
property: field,
values,
datas,
filters: filterList,
filterList
};
// 如果是服务端筛选,则跳过本地筛选处理
if (!filterOpts.remote) {
$xeTable.handleTableData(true);
$xeTable.checkSelectionStatus();
}
if (mouseConfig && mouseOpts.area && $xeTable.handleFilterEvent) {
$xeTable.handleFilterEvent(evnt, params);
}
if (evnt) {
$xeTable.dispatchEvent('filter-change', params, evnt);
}
$xeTable.closeFilter();
return $xeTable.updateFooter().then(() => {
const {
scrollXLoad,
scrollYLoad
} = reactData;
if (oldScrollXLoad || scrollXLoad || oldScrollYLoad || scrollYLoad) {
if (oldScrollXLoad || scrollXLoad) {
$xeTable.updateScrollXSpace();
}
if (oldScrollYLoad || scrollYLoad) {
$xeTable.updateScrollYSpace();
}
return $xeTable.refreshScroll();
}
}).then(() => {
$xeTable.updateCellAreas();
return $xeTable.recalculate(true);
}).then(() => {
// 存在滚动行为未结束情况
setTimeout(() => $xeTable.recalculate(), 50);
});
},
/**
* 确认筛选
* 当筛选面板中的确定按钮被按下时触发
* @param {Event} evnt 事件
*/
confirmFilterEvent(evnt) {
const {
filterStore
} = reactData;
const {
column
} = filterStore;
$xeTable.handleColumnConfirmFilter(column, evnt);
},
handleFilterChangeRadioOption: changeRadioOption,
handleFilterChangeMultipleOption: changeMultipleOption,
// 筛选发生改变
handleFilterChangeOption(evnt, checked, item) {
const {
filterStore
} = reactData;
if (filterStore.multiple) {
changeMultipleOption(evnt, checked, item);
} else {
changeRadioOption(evnt, checked, item);
}
},
handleFilterConfirmFilter,
handleFilterResetFilter
};
const filterMethods = {
/**
* 手动弹出筛选面板
* @param column
*/
openFilter(fieldOrColumn) {
const column = (0, _util.handleFieldOrColumn)($xeTable, fieldOrColumn);
if (column && column.filters) {
const {
elemStore
} = internalData;
const {
fixed
} = column;
return $xeTable.scrollToColumn(column).then(() => {
const headerWrapperElem = (0, _util.getRefElem)(elemStore[`${fixed || 'main'}-header-wrapper`] || elemStore['main-header-wrapper']);
if (headerWrapperElem) {
const filterBtnElem = headerWrapperElem.querySelector(`.vxe-header--column.${column.id} .vxe-filter--btn`);
(0, _dom.triggerEvent)(filterBtnElem, 'click');
}
});
}
return (0, _vue.nextTick)();
},
/**
* 修改筛选条件列表
* @param {ColumnInfo} fieldOrColumn 列或字段名
* @param {Array} options 选项
*/
setFilter(fieldOrColumn, options, isUpdate) {
const column = (0, _util.handleFieldOrColumn)($xeTable, fieldOrColumn);
if (column && column.filters) {
column.filters = (0, _util.toFilters)(options || []);
if (isUpdate) {
return $xeTable.handleColumnConfirmFilter(column, new Event('click'));
}
}
return (0, _vue.nextTick)();
},
/**
* 清空指定列的筛选条件
* 如果为空则清空所有列的筛选条件
* @param {String} fieldOrColumn 列或字段名
*/
clearFilter(fieldOrColumn) {
const {
filterStore
} = reactData;
const {
tableFullColumn
} = internalData;
const filterOpts = computeFilterOpts.value;
let column;
if (fieldOrColumn) {
column = (0, _util.handleFieldOrColumn)($xeTable, fieldOrColumn);
if (column) {
filterPrivateMethods.handleClearFilter(column);
}
} else {
tableFullColumn.forEach(filterPrivateMethods.handleClearFilter);
}
if (!fieldOrColumn || column !== filterStore.column) {
Object.assign(filterStore, {
isAllSelected: false,
isIndeterminate: false,
style: null,
options: [],
column: null,
multiple: false,
visible: false
});
}
if (!filterOpts.remote) {
return $xeTable.updateData();
}
return (0, _vue.nextTick)();
},
saveFilterPanel() {
handleFilterConfirmFilter(null);
return (0, _vue.nextTick)();
},
resetFilterPanel() {
handleFilterResetFilter(null);
return (0, _vue.nextTick)();
},
getCheckedFilters() {
const {
tableFullColumn
} = internalData;
const filterList = [];
tableFullColumn.forEach(column => {
const {
field,
filters
} = column;
const valueList = [];
const dataList = [];
if (filters && filters.length) {
filters.forEach(item => {
if (item.checked) {
valueList.push(item.value);
dataList.push(item.data);
}
});
if (valueList.length) {
filterList.push({
column,
field,
property: field,
values: valueList,
datas: dataList
});
}
}
});
return filterList;
},
updateFilterOptionStatus(item, checked) {
item._checked = checked;
item.checked = checked;
return (0, _vue.nextTick)();
}
};
return Object.assign(Object.assign({}, filterMethods), filterPrivateMethods);
},
setupGrid($xeGrid) {
return $xeGrid.extendTableMethods(tableFilterMethodKeys);
}
});