UNPKG

shu-c-view

Version:

rollup 打包vue组件库框架

767 lines (765 loc) 21.6 kB
/** * @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 };