UNPKG

kingdot

Version:

A UI Components Library For Vue

666 lines (619 loc) 20.2 kB
import {ulid} from "../../src/utils/utils.js"; //列最小宽度 const columnMinWidth = 100; //对比数据唯一标识,是否在存储数据中包含该条数据 const uniqProcess = function (rowData, transactionData, key) { let result = false; let index = -1; transactionData.forEach((item, _index) => { if (result) return false; result = item[key] === rowData[key]; if (result) { index = _index } }) return {result, index} } //遍历数据,增加一些参数 const parseData = function ( data, disableRow, transactionData, key, stored ) { let outData = []; data.forEach((item, index) => { item.__index__ = index; let _checked = item.checked; if (stored) { let {result} = uniqProcess(item, transactionData, key); _checked = result; } outData.push({ originData: item, checked: _checked, showExpand: false, showTree: item.showTree || false, key: ulid(), disabled: disableRow(item, index) }); }); return outData; }; //获取对应的value值。支持"a", "a.b", "a.b.c" function getRealyProps(data, propsArray) { if (!data) return ""; if (propsArray.length > 1) { var _data = data[propsArray[0]]; propsArray.shift(); return getRealyProps(_data, propsArray); } else { return data[propsArray[0]]; } } //处理a.b 排序 function sortBy(attr, rev) { if (rev == undefined) { rev = 1; } else { rev = rev ? 1 : -1; } attr = attr.split('.') return function (a, b) { a = getRealyProps(a, Object.assign([], attr)); b = getRealyProps(b, Object.assign([], attr)); if (a < b) { return rev * -1; } else if (a > b) { return rev * 1; } return 0; }; } function mapHasChildrenColumn(item, hasWidthFn, hasNoWidthFn, hasPropsFn) { if (item.props || item.renderColumnFn) { if (item.width) { hasWidthFn && hasWidthFn(item.width) } else { hasNoWidthFn && hasNoWidthFn(); } hasPropsFn && hasPropsFn(); } if (item.children && item.children.length) { item.children.map(inner => { mapHasChildrenColumn(inner, hasWidthFn, hasNoWidthFn, hasPropsFn); }) } } const TableStore = function (table, initState = {}) { this.table = table; let checkboxWidth = 34; this.checkboxData = { width: checkboxWidth, autoColumnWidth: checkboxWidth, deviation: 0, native: true, renderHeaderFn: (h, {self, data, store}) => { return !initState.isRadio ? ( <kd-checkbox trueValue={true} indeterminate={store.states.checkboxIndeterminate} value={store.states._isCheckAll} on-change={v => { store.states._isCheckAll = v; store.checkboxAllAction(v); }} ></kd-checkbox> ) : ( "" ); }, renderColumnFn: (h, {data, store}) => { //判断是否有key,children没有key,不显示checkbox if (!data.key) { return (''); } return !initState.isRadio ? ( <kd-checkbox trueValue={true} value={data.checked} on-change={v => { data.checked = v; store.checkboxSingle(data.originData, v); }} disabled={data.disabled} ></kd-checkbox> ) : ( <kd-radio trueValue={true} value={data.checked} on-change={v => { store.checkedRadio(data, v) }} disabled={data.disabled} ></kd-radio> ); }, _slotHeader: true, _slotColumn: true, checked: true, fixedLeft: true, fixedRight: false }; let expandWith = 30; this.expandData = { width: expandWith, autoColumnWidth: expandWith, deviation: 0, renderColumnFn: (h, {data, store}) => { return ( <i class={ [ "kd-table-btn", "kd-icon-arrow-down", { "kd-table-show-btn": data.showExpand } ] } on-click={v => { store.showMore(data); }} ></i> ) }, _slotHeader: false, _slotColumn: true, fixedLeft: true, fixedRight: false }; this.states = { //head列 columns: [], //数据 data: null, //是否全选 _isCheckAll: false, //是否显示checkbox showCheckbox: true, checkboxIndeterminate: false, _columns: [], //table外围总宽度 layoutWidth: "", //左侧固定宽度 fixedLeftWidth: "", //右侧固定宽度 fixedRightWidth: "", //右侧固定偏移量 marginfixedRightWidth: "", //左侧固定的列 fixedColumns: [], //是否有左侧固定列 hasFiexLeft: false, //是否有右侧固定列 hasFiexRight: false, //右侧固定的列 rightFixedColumns: [], //是否所有的列都设置了宽度 isAllColumnSetWidth: false, //未设置宽度的列的个数 _unPropsColumnWidthCount: 0, //设置宽度的列的个数 _propsColumnWidthCount: 0, //设置了列的宽度的总值 _propsColumnWidthSum: 0, //计算未设置宽度的列的值 _autoColumnWidth: 0, //table外围container宽度 _outInputLayoutWidth: 0, //table总宽度 _layoutWidth: 0, _columnMinWidth: columnMinWidth, //disabled方法 disableRow: null, //是否存储每次选中 stored: false, //存储选中的数据 _innerCheckedData: [], //data唯一标识 _keyStr: '', //排序升序 key _sortAsc: '', //排序降序 key _sortDesc: '', //存储那个key在排序 _sortProps: '', //存储是否在排序 _sortIsAsc: '', expand: null } this.selectCallback = initState.selectCallback || null; //覆盖states里属性 for (let prop in initState) { if ( initState.hasOwnProperty(prop) && this.states.hasOwnProperty(prop) ) { this.states[prop] = initState[prop]; } } }; TableStore.prototype.mutation = { //插入head列 insertColumn: function (column, index) { let _columns = this.states._columns; if (index < _columns.length) { _columns.splice(index, 0, column); } else { _columns.push(column); } this.table.updateColumnData(); this._render(); }, //删除head列 deleteColumn: function (key) { const _colums = Object.assign([], this.states._columns); const index = _colums.findIndex(item => item.key === key); _colums.splice(index, 1); this.states._columns = _colums; this.table.updateColumnData(); this._render(); }, //插入expand数据 insertExpand: function (v) { this.states.expand = v; }, //更新data数据 updateData: function (v) { var data = parseData( v, this.states.disableRow, this.states._innerCheckedData, this.states._keyStr, this.states.stored ); this.states.data = data; this.checkboxStatus(); } }; //操作 TableStore.prototype.commit = function () { var args = Object.assign([], arguments); const actionName = args.splice(0, 1); if (this.mutation[actionName]) this.mutation[actionName].apply(this, args); }; //渲染 TableStore.prototype._render = function () { this.update(); }; TableStore.prototype.update = function () { const states = this.states; //筛选出需要显示的 const _columns = states._columns.filter(item => item.isShow) || []; let setColumns = []; let setFixedColumns = []; let setFixedRightColumns = []; //设置列宽的个数 let setWidthCount = 0; //设置了宽度的列的宽度总值 let setWidth = 0; //隐藏的列的个数 let hidenColumnsCount = 0; //合并表头时的无宽度的children let childrenCount = 0; let allLength = 0; //筛选列 _columns.forEach(item => { if (!item.isShow) hidenColumnsCount++; //if (!item.width) return; // setWidth += Number.parseInt(item.width); // setWidthCount++; mapHasChildrenColumn( item, //有宽度 function (width) { setWidth += Number.parseInt(width); setWidthCount ++; }, //无宽度 function () { childrenCount ++; }, //有效的列 function(){ allLength ++; } ) }) states.showCheckbox && (setWidth += this.checkboxData.width); states.expand && (setWidth += this.expandData.width); //判断列数,如果是头部合并则取所有有效列个数。 let colunmLength = allLength > _columns.length ? allLength : _columns.length; //判断是否所有的列都设置了宽度 this.states.isAllColumnSetWidth = setWidthCount == colunmLength; //判断未设置宽度的列的个数 列总数 - 设置宽度的列 - 隐藏的列 this.states._unPropsColumnWidthCount = colunmLength - setWidthCount - hidenColumnsCount; //存储设置了宽度的列的总数 this.states._propsColumnWidthCount = setWidthCount; //存储设置了宽度的列的宽度总值 this.states._propsColumnWidthSum = setWidth; this._setColumnAutoWidth(); this.renderLayout(); //判断是否有左右固定列 this.states.hasFiexLeft = _columns.findIndex(item => item.fixedLeft) > -1; this.states.hasFiexRight = _columns.findIndex(item => item.fixedRight) > -1; //autoColumnWidth = width _columns.forEach( item => (item.autoColumnWidth = item.width ? item.width : "") ); setColumns = setFixedColumns.concat( _columns.filter(item => item) ); //获取左侧固定列 setFixedColumns = _columns.filter(item => item.fixedLeft); //获取右侧固定列 setFixedRightColumns = _columns.filter(item => item.fixedRight); //判断是否有expand的column if (states.expand) { //有左侧fixed if (states.hasFiexLeft) { setFixedColumns.unshift(this.expandData); } setColumns.unshift(this.expandData); } //checkbox模式 if (states.showCheckbox) { //有左侧fixed if (states.hasFiexLeft) { setFixedColumns.unshift(this.checkboxData); } setColumns.unshift(this.checkboxData); } this.states.fixedColumns = setFixedColumns; // this.states.columns = states._columns; this.states.columns = setColumns; this.states.rightFixedColumns = setFixedRightColumns; }; //处理table总宽 TableStore.prototype._setColumnAutoWidth = function () { let states = this.states; let { _unPropsColumnWidthCount, _outInputLayoutWidth, _propsColumnWidthSum, isAllColumnSetWidth } = states; //未设置宽度的列剩余宽度总值 container宽度 - 设置了宽度的列的宽度总值 let autoWidthSum = _outInputLayoutWidth - _propsColumnWidthSum; //未设置宽度的列个数 * 最小列宽 > 剩余宽度 if (_unPropsColumnWidthCount * columnMinWidth > autoWidthSum) { //未设置列的宽度统一设置成最小宽度 this.states._autoColumnWidth = columnMinWidth; //重置未设置列的宽度总值 autoWidthSum = _unPropsColumnWidthCount * columnMinWidth; } else { //未设置列的宽度 = 剩余宽度 / 未设置宽度的列个数 this.states._autoColumnWidth = autoWidthSum / _unPropsColumnWidthCount } //如果所有列都是设置宽度 if (isAllColumnSetWidth) { this.states._layoutWidth = _propsColumnWidthSum >= states._layoutWidth ? _propsColumnWidthSum : states._layoutWidth } else { this.states._layoutWidth = _propsColumnWidthSum + autoWidthSum; } } TableStore.prototype.renderLayout = function () { let states = this.states; let columns = states._columns; //fixed左侧宽度 let fixedLeftWdith = 0; //fixed右侧的宽度 let fixedRightWdith = 0; //计算左右fixed宽度 states.fixedColumns = columns.filter(item => { if (item.fixedLeft && item.isShow) { let width = item.width || states._autoColumnWidth; fixedLeftWdith += Number.parseInt(width) + item.deviation || 0; return true; } }); //左侧增加Checkbox宽度 if (states.showCheckbox && fixedLeftWdith > 0) { fixedLeftWdith += this.checkboxData.width } //左侧增加expand宽度 if (states.expand && fixedLeftWdith > 0) { fixedLeftWdith += this.expandData.width } states.fixedColumns = columns.filter(item => { if (item.fixedRight && item.isShow) { let width = item.width || states._autoColumnWidth; fixedRightWdith += Number.parseInt(width) + item.deviation || 0; return true; } }); this.states.fixedLeftWidth = fixedLeftWdith + 'px'; this.states.fixedRightWidth = fixedRightWdith + 'px'; this.states.layoutWidth = states._layoutWidth + 'px'; this.states.marginfixedRightWidth = fixedRightWdith - states._layoutWidth + 'px'; } //设置table外围container宽度 TableStore.prototype.setLayoutWidth = function (width) { this.states._outInputLayoutWidth = width; this._render(); }; //设置td偏移量 TableStore.prototype.setColumndeviation = function (key, value) { let _columns = this.states._columns; let index = _columns.findIndex(item => item.key == key); this.states._columns[index].deviation += value; this.update(); }; //全选 TableStore.prototype.checkboxAllAction = function (v) { let states = this.states; states._isCheckAll = v; states.checkboxIndeterminate = false; states.data.forEach(item => { if (item.disabled) return; // 如果item之前已选中的 且 触发全选中 if(item.checked && v) return; item.checked = v; //如果开启了存储选中状态 if (states.stored) { let {result, index} = uniqProcess(item.originData, states._innerCheckedData, states._keyStr); if (states._isCheckAll) { // 暂存数据中包含本行数据 if (result) { states._innerCheckedData.splice(index, 1); } else { states._innerCheckedData.push(item.originData); } } else { //若包含本数据,则移除 if (result) { states._innerCheckedData.splice(index, 1); } } } }); this.update(); this.selectCallback && this.selectCallback(this.getCheckedData()) }; //单选 TableStore.prototype.checkboxSingle = function (rowData, checked) { let states = this.states; let checkCount = 0; states.data.forEach(item => { item.checked && checkCount++; if (!rowData) return false; }) //获取除去disabled所有 let dataCount = states.data.filter(item => !item.disabled).length; if (checkCount == 0) { states._isCheckAll = false; states.checkboxIndeterminate = false; } else { if (dataCount == checkCount) { states._isCheckAll = true; states.checkboxIndeterminate = false; } else { states._isCheckAll = false; states.checkboxIndeterminate = true; } } if (rowData && states.stored) { let {result, index} = uniqProcess( rowData, states._innerCheckedData, states._keyStr ); if (checked) { // 暂存数据中包含本行数据 if (result) { states._innerCheckedData.splice(index, 1); } else { states._innerCheckedData.push(rowData); } } else { //若包含本数据,则移除 if (result) { states._innerCheckedData.splice(index, 1); } } } this.update(); if(checked === true || checked === false){ this.selectCallback && this.selectCallback(this.getCheckedData()) } }; //radio TableStore.prototype.checkedRadio = function (rowData, checked) { let states = this.states; states.data.forEach(item => { item.checked && (item.checked = false); if (!rowData) return false; }); rowData.checked = checked; states._innerCheckedData = [rowData.originData]; } //获取当前选中的数据 TableStore.prototype.getCheckedData = function () { if (this.states.stored) return this.states._innerCheckedData; let dataOut = []; this.states.data.forEach(item => { item.checked && dataOut.push(item.originData); }); return dataOut; }; //排序 TableStore.prototype.orderAction = function ( props, columnkey, isAsc, sortable ) { if (sortable) { let _data = Object.assign( [], this.states.data.map(item => item.originData) ); let sortDate = _data.sort(sortBy(props, isAsc)); this.states._sortAsc = ''; this.states._sortDesc = ''; this.states._sortProps = props; this.states._sortIsAsc = isAsc; if (isAsc) { this.states._sortAsc = columnkey; } else { this.states._sortDesc = columnkey; } this.commit("updateData", sortDate); } } //排序,用于数据变化时 TableStore.prototype.updateDataKeepSort = function (data, props, isAsc) { //截取数组,原数组已经被vue监控,存在observer let _data = data.slice(0); let sortDate = _data.sort(sortBy(props, isAsc)); this.commit("updateData", sortDate); }; //重置checkbox选中 TableStore.prototype.checkboxStatus = function () { this.checkboxSingle(); }; //显示table tr 下详情 TableStore.prototype.showMore = function (data) { let $index = null; let flag = null; this.states.data.forEach((item, index) => { if (item.key === data.key) { $index = index; item.showExpand = !item.showExpand; flag = item.showExpand; return false; } }); this.table.lazyLoadExpand(data.originData, $index, flag) } TableStore.prototype.outUpdate = function (keys, keysValue) { this.setColumns(keys, keysValue); this.update() } //重置是否显示列 TableStore.prototype.setColumns = function (keys, value = false) { this.states._columns.forEach(item => { keys.indexOf(item.key) > -1 ? (item.isShow = value) : (item.isShow = !value); }); }; export default TableStore;