shu-c-view
Version:
rollup 打包vue组件库框架
767 lines (765 loc) • 21.6 kB
JavaScript
/**
* @desc grid 列表组件
*/
import _get from 'lodash/get';
import _has from 'lodash/has';
import _omit from 'lodash/omit';
import _set from 'lodash/set';
import _assign from 'lodash/assign';
import _isNil from 'lodash/isNil';
import _isArray from 'lodash/isArray';
import _isEmpty from 'lodash/isEmpty';
import _includes from 'lodash/includes';
import _findIndex from 'lodash/findIndex';
import { devConsole } from '../helper/util.js';
import { BaseTBar } from './t-bar/index.js';
import { BaseGridSearch } from './search/index.js';
import { BaseGridTable } from './table/index.js';
import { BaseGridPagination } from './pagination/index.js';
const BaseGrid = {
name: 'BaseGrid',
provide() {
return {
getBaseGrid: this
};
},
components: {
BaseGridPagination,
BaseGridTable,
BaseGridSearch,
BaseTBar
},
props: {
// api接口
api: {
type: String,
required: true
},
// 初始查询条件
queryParams: {
type: Object,
default() {
return {};
}
},
// 自定义样式
ctCls: {
type: Object,
default() {
return {};
}
},
// 列 el-table-column 的配置
columns: {
type: Array,
default() {
return [];
}
},
// 是否多选
selectMode: {
type: Boolean,
default: false
},
// 是否显示index下标列
isShowIndex: {
type: Boolean,
default: false
},
// 下标行的名称
indexLabel: {
type: String,
default: '序号'
},
// 默认选择第一行
isSelectedFirstRow: {
type: Boolean,
default: false
},
// 第一次载入时是否自动刷新列表数据
isReloadGrid: {
type: Boolean,
default: true
},
// 是否显示分页数量选择器
isShowPagination: {
type: Boolean,
default: true
},
// v-if
isRender: {
type: Boolean,
default: true
},
// v-show
isDisplay: {
type: Boolean,
default: true
},
// Table Attributes
tableAttributes: {
type: Object,
default() {
return {};
}
},
// Pagination Attributes
paginationAttributes: {
type: Object,
default() {
return {};
}
},
// 过滤返回数据(该函数带一个参数'data'用来指向源数据)
loadFilter: {
type: Function,
default: data => data
},
loadResponseFilter: {
type: Function,
default: data => data
},
// 静态数据(api设置为空)
options: {
type: Object
},
// 静态数据是否需要进行分页操作
isOptionsPage: {
type: Boolean,
default: true
},
// 自定义当前分页参数 {page: 'page',size: 'size',total: 'data.total',data: 'data.records',pageNum: 'current',pageSize: 'size'}
pagingParams: {
type: Object
},
// 是否冻结下标列
isFixedIndex: {
type: Boolean,
default: false
},
// 是否冻结多选框列
isFixedSelection: {
type: Boolean,
default: false
},
// 插槽操作列配置
columnTool: {
type: Object,
default() {
return {
label: '操作'
// fixed: 'right'
};
}
},
// 序号是否连续性
isContinuityIndex: {
type: Boolean,
default: false
},
// 推荐 id 作为唯一键(使用`isKeepSelectedRow`时需要设置)
nodeKey: {
type: String,
default: 'id'
},
// 多选情况下选中行是否在翻页回来后继续选中,保持选中状态
isKeepSelectedRow: {
type: Boolean,
default: false
},
// 多选最多能选中几个(isKeepSelectedRow 为true时也会被计算在选中的几个之内)
selectModeMaxNum: {
type: Number
},
// 搜索栏的位置
paginationPosition: {
type: String,
default: 'south',
validator(value) {
// 这个值必须匹配下列字符串中的一个
return ['north', 'south'].indexOf(value) !== -1;
}
},
// 是否显示分页栏的刷新小图标
isRenderRefreshIcon: {
type: Boolean,
default: true
},
// 要禁用选中复选款的行,需要设置 nodeKey
disabledSelectRows: {
type: Array,
default() {
return [];
}
},
// 固定的行-`rowIndex`行下标,第一行:0 第二行:1
// :fixed-rows="0"
fixedRow: {
type: Number
},
// 分页参数定义类型-current和size
paginationParamType: {
type: String,
default: 'params',
validator(value) {
return ['params', 'data'].includes(value);
}
}
},
data() {
this.layout = 'border'; // 布局
this.baseGridTable = null; // table 组件实例
this.paginationInstance = null; // Pagination 分页 组件实例
this.events = {
onLoadSuccess: 'onLoadSuccess', // 在数据加载成功的时候触发
onLoadError: 'onLoadError', // 在载入远程数据产生错误的时候触发
onBeforeLoad: 'onBeforeLoad', // 在载入请求数据之前触发,如果返回 false 可终止载入数据操作(验证参数)
onChangeRowEvent: 'onChangeRowEvent' // 选中行事件-单选
};
this.currentPageTable = [];
return {
currentRow: {}, // 当前选中行
contextMenuRow: {}, // 右键点击行
contextMenuColumn: {}, // 右键点击列
currentPage: _get(
this.paginationAttributes,
'currentPage',
_get(
this['$base-global-options'],
'grid.paginationAttributes.currentPage',
''
)
), // 当前页数
pageSize: _get(
this.paginationAttributes,
'pageSize',
_get(
this['$base-global-options'],
'grid.paginationAttributes.pageSize',
''
)
), // 每页显示条目个数
total: 0, // 总条目数
curSelectValueList: [] // 翻页多选行 nodeKey 的值
};
},
watch: {
paginationAttributes: {
handler(val) {
if (_has(val, 'pageSize')) {
this.pageSize = val.pageSize;
}
if (_has(val, 'currentPage')) {
this.currentPage = val.currentPage;
}
},
immediate: true
},
selectMode: {
handler(val) {
if (val) {
this.setKeepSelectedRecords();
}
},
immediate: true
}
},
created() {
if (_isNil(this.currentPage)) {
this.currentPage = 1;
}
if (_isNil(this.pageSize)) {
this.pageSize = 30;
}
if (
!_isEmpty(this.paginationAttributes) &&
_has(this.paginationAttributes, 'current-page')
) {
// 不是第一页
this.currentPage = _get(this.paginationAttributes, 'current-page');
}
const pageSizeField = _get(
this['$base-global-options'],
'grid.pageSize',
'pageSize'
);
if (
!_isNil(this.options) &&
!_isNil(this.options.data) &&
_has(this.options.data, pageSizeField)
) {
this.pageSize = _get(this.options.data, pageSizeField); // 设置静态数据一页加载的数据量
}
// this.setKeepSelectedRecords();
},
methods: {
/**
* @desc 设置表格的总数量
* @param {Number} num=0 - 数量
*/
setTotal(num = 0) {
this.total = num;
},
/**
* @desc 设置 baseGridTable 组件实例
* @method
* @param {Object} tableInstance - 组件实例对象 this
*/
setTableEl(tableInstance) {
this.baseGridTable = tableInstance;
},
/**
* @desc 设置查询参数
* @param {Object} params - 查询对象参数
*/
setQueryParams(params = {}) {
this.getTable().setQueryParams(params);
},
/**
* @desc 获取 BaseGridTable 组件实例
* @method
* @returns {Object} BaseGridTable 组件的实例对象 this
*/
getTable() {
return this.baseGridTable;
},
/**
* @desc 获取 el-table 组件实例(用于直接操作 element-ui的el-table组件的方法)
* @method
* @returns {Object} el-table组件
*/
getElTable() {
return this.baseGridTable.getEl();
},
/**
* @desc 获取查询总数
* @method
* @returns {Number} 总数
*/
getTotal() {
return this.total;
},
/**
* @desc 获取总页数
* @method
* @returns {Number} 总页数
*/
getTotalPages() {
return Math.ceil(this.total / this.pageSize);
},
/**
* @desc 获取当前页
* @returns {Number} 当前页
*/
getCurrentPage() {
return this.currentPage;
},
/**
* @desc 获取当前页条数
* @returns {Number} 当前页条数
*/
getPageSize() {
return this.pageSize;
},
/**
* @desc 返回加载完毕后的数据
* @method
* @returns {Array}
*/
getData() {
return this.getTable().tableData;
},
/**
* @desc 返回单选选中的行-单选
* @method
* @returns {Object}
*/
getSelected() {
return this.getTable().getSelectedRow();
},
/**
* @desc 返回复选时所有被选中的行-多选
* @method
* @returns {Array}
*/
getSelections() {
return this.getTable().getSelectedRows();
},
/**
* @desc 选中一行-单选
* @method
*/
selectRow(row = {}) {
this.getTable().setCurrentRow(row);
},
/**
* @desc 选择多行
* @method
*/
selectRows(rows = []) {
this.getTable().toggleRowSelection(rows);
setTimeout(() => {
const selections = this.getSelections();
for (let i = 0, length = selections.length; i < length; i++) {
if (
!_includes(this.curSelectValueList, selections[i][this.nodeKey])
) {
this.curSelectValueList.push(selections[i][this.nodeKey]);
}
}
}, 0);
},
/**
* @desc 选择当前页中所有的行
*/
selectAll() {
this.getTable().toggleAllSelection();
},
/**
* @desc 用于多选表格,清空用户的选择
* @method
*/
clearSelection() {
const selections = this.getSelections();
for (let i = 0, length = selections.length; i < length; i++) {
const valueIndex = _findIndex(
this.curSelectValueList,
item => item === selections[i][this.nodeKey]
);
if (valueIndex !== -1) {
this.curSelectValueList.splice(valueIndex, 1);
}
}
this.getElTable().clearSelection();
},
/**
* @desc 刷新 table 组件,会回到第一页
* @method
*/
reloadGrid() {
this.currentPage = 1;
if (!_isNil(this.options)) {
this.getTable().loadOptions();
} else {
this.getTable().loadData();
}
},
/**
* @desc 刷新 table 组件,保留在当前页
* @method
*/
loadGrid() {
if (!_isNil(this.options)) {
this.getTable().loadOptions();
} else {
this.getTable().loadData();
}
},
/** Pagination 分页组件 */
/**
* @desc 设置 BaseGridPagination 组件实例
* @method
* @param {Object} paginationInstance - 组件实例对象 this
*/
setPaginationEl(paginationInstance) {
this.paginationInstance = paginationInstance;
},
/**
* @desc 获取 BaseGridPagination 组件实例
* @method
* @returns {Object} BaseGridPagination 组件的实例对象 this
*/
getPagination() {
return this.paginationInstance;
},
/**
* @desc pageSize 改变时会触发
* @param {number} pageSize - 每页条数
* @method
*/
onSizeChange(pageSize) {
this.pageSize = pageSize;
if (this.currentPage === 1 || this.currentPage * pageSize <= this.total) {
this.loadGrid();
} else {
this.currentPage = 1;
this.loadGrid();
}
},
/**
* @desc currentPage 改变时会触发
* @param {number} page - 当前页
* @method
*/
onCurrentChange(page) {
this.currentPage = page;
this.loadGrid();
},
/**
* @desc 在数据加载成功的时候触发
* @param {Array} table
* @method
*/
onLoadSuccess(table) {
this.currentPageTable = table;
this.$emit(this.events.onLoadSuccess, table);
if (
this.isKeepSelectedRow &&
this.selectMode &&
!_isEmpty(this.curSelectValueList)
) {
this.keepSelectedRowHandle(table);
}
},
/**
* @desc 在载入远程数据产生错误的时候触发
* @method
*/
onLoadError() {
this.$emit(this.events.onLoadError);
},
/**
* @desc 更新选中行
* @param {Object} row - 选中行(如果是复选也只会是当前点击的这行)
* @method
*/
updateCurrentRow(row) {
this.currentRow = row;
this.$emit(this.events.onChangeRowEvent, row);
},
/**
* @desc 更新右键选中记录 行和列
* @param {Object} row - 选中行
* @param {Object} column - 选中列
* @method
*/
updateContextMenuSelectedRecord(row = {}, column = {}) {
this.contextMenuRow = row;
this.contextMenuColumn = column;
},
/**
* @description 强制刷新表格ui
*/
refreshTable() {
this.$nextTick(() => {
this.getTable()
.getEl()
.doLayout();
});
},
// 设置保持选中的记录行
setKeepSelectedRecords() {
// 多选情况下是否保持选中行
if (this.isKeepSelectedRow && this.selectMode) {
this.$off('_select-all');
this.$off('_select');
this.$on('_select', function(selection, row) {
const values = _assign([], this.curSelectValueList);
for (let i = 0, length = selection.length; i < length; i++) {
if (!_includes(values, selection[i][this.nodeKey])) {
values.push(selection[i][this.nodeKey]);
}
}
const rowSelectIndex = _findIndex(
selection,
item => _get(item, this.nodeKey) === _get(row, this.nodeKey)
);
if (rowSelectIndex === -1) {
// 当前行是取消选中状态
const rowValuesIndex = _findIndex(
values,
item => item === _get(row, this.nodeKey)
);
values.splice(rowValuesIndex, 1);
}
this.curSelectValueList = values;
});
this.$on('_select-all', function(selection) {
const values = _assign([], this.curSelectValueList);
const data = _isEmpty(selection) ? this.currentPageTable : selection;
for (let i = 0, length = data.length; i < length; i++) {
if (_isEmpty(selection)) {
const rowSelectIndex = _findIndex(
values,
item => item === _get(data[i], this.nodeKey)
);
if (rowSelectIndex !== -1) {
values.splice(rowSelectIndex, 1);
}
} else if (
!_isEmpty(selection) &&
!_includes(values, data[i][this.nodeKey])
) {
values.push(data[i][this.nodeKey]);
}
}
this.curSelectValueList = values;
});
}
},
// 选中保持选中的记录行
keepSelectedRowHandle() {
// 翻页时如果当前页有要选中的行那么设置选中效果
setTimeout(() => {
const selectRows = [];
for (
let i = 0, length = this.curSelectValueList.length;
i < length;
i++
) {
selectRows.push({
field: this.nodeKey,
value: this.curSelectValueList[i]
});
}
this.selectRows(selectRows);
}, 0);
},
// 获取所有选中行,包括 isKeepSelectedRow 为 true
getAllKeepSelectRows() {
return this.curSelectValueList;
}
},
render(h) {
// v-if
if (!this.isRender) {
return h();
}
const style = {};
// v-show
if (!this.isDisplay) {
_set(style, 'display', 'none');
}
return h(
'base-border-layout',
{
ref: `${this._uid}-base-grid`,
style,
class: _assign({ 'base-grid': true }, _get(this.$props, 'ctCls', {})),
props: {
northHeight: 'auto',
westWidth: '0px',
eastWidth: '0px',
southHeight: this.isShowPagination ? '36px' : '0px',
isPadding: false
}
},
[
this.paginationPosition === 'south'
? h(
'base-border-layout',
{
slot: 'north',
props: {
northHeight: 'auto',
southHeight: 'auto',
isPadding: false
}
},
[
h(
BaseGridSearch,
{
slot: 'north',
scopedSlots: {
searchScope: () => {
if (_has(this.$scopedSlots, 'searchScope')) {
return this.$scopedSlots.searchScope(this.currentRow);
}
return h();
}
}
},
[h('template', { slot: 'default' }, this.$slots.search)]
),
h(
BaseTBar,
{
slot: 'south',
scopedSlots: {
tBarScope: () => {
if (_has(this.$scopedSlots, 'tBarScope')) {
return this.$scopedSlots.tBarScope(this.currentRow);
}
return h();
}
}
},
[h('template', { slot: 'default' }, this.$slots.tBar)]
)
]
)
: h(),
h(
BaseGridTable,
{
slot: 'center',
props: {
api: this.api,
queryParams: this.queryParams,
columns: this.columns,
isReloadGrid: this.isReloadGrid,
isSelectedFirstRow: this.isSelectedFirstRow,
isShowIndex: this.isShowIndex,
indexLabel: this.indexLabel,
selectMode: this.selectMode,
loadFilter: this.loadFilter,
loadResponseFilter: this.loadResponseFilter,
slotNode: this.tableAttributes.slotNode,
tableAttributes: this.tableAttributes,
options: this.options,
pagingParams: this.pagingParams,
isFixedIndex: this.isFixedIndex,
isFixedSelection: this.isFixedSelection,
columnTool: this.columnTool,
isContinuityIndex: this.isContinuityIndex,
isOptionsPage: this.isOptionsPage,
selectModeMaxNum: this.selectModeMaxNum,
nodeKey: this.nodeKey,
disabledSelectRows: this.disabledSelectRows,
fixedRow: this.fixedRow,
paginationParamType: this.paginationParamType
}
},
[]
),
h(
BaseGridPagination,
{
slot: this.paginationPosition === 'south' ? 'south' : 'north',
props: {
currentPage: this.currentPage,
pageSize: this.pageSize,
pagingItems: this.paginationAttributes.pagingItems,
paginationAttributes: _omit(this.paginationAttributes, [
'currentPage',
'pageSize',
'isShowPagination',
'pagingItems'
]),
total: this.total,
isShowPagination: this.isOptionsPage
? this.isShowPagination
: false,
isRenderRefreshIcon: this.isRenderRefreshIcon
}
},
[]
)
]
);
}
};
BaseGrid.install = function(Vue, ElComponents) {
// 用于按需加载的时候独立使用
devConsole(`按需加载独立组件:${BaseGrid.name}`);
if (_isArray(ElComponents) && !_isEmpty(ElComponents)) {
for (let i = 0; i < ElComponents.length; i++) {
if (ElComponents[i].name !== BaseGrid.name) {
Vue.use(ElComponents[i]);
}
}
}
Vue.component(BaseGrid.name, BaseGrid);
};
export { BaseGrid };