UNPKG

shu-c-view

Version:

rollup 打包vue组件库框架

1,356 lines (1,353 loc) 49.5 kB
/** * @desc select-tree 选择器 */ import _assign from 'lodash/assign'; import _includes from 'lodash/includes'; import _findIndex from 'lodash/findIndex'; import _isNil from 'lodash/isNil'; import _toNumber from 'lodash/toNumber'; import _isEmpty from 'lodash/isEmpty'; import _has from 'lodash/has'; import _omit from 'lodash/omit'; import _isArray from 'lodash/isArray'; import _isEqual from 'lodash/isEqual'; import _difference from 'lodash/difference'; import _filter from 'lodash/filter'; import _map from 'lodash/map'; import _get from 'lodash/get'; import _isString from 'lodash/isString'; import _find from 'lodash/find'; import _forEach from 'lodash/forEach'; import { devConsole } from '../helper/util.js'; const BaseSelectTree = { name: 'BaseSelectTree', inheritAttrs: false, model: { prop: 'selectTreeValue', event: 'selectTreeChange' }, props: { // 传入默认选中值 ['',''] String 需要默认选中时请结合 'defaultCheckedKeys' 参数 // 值的匹配必须和 'defaultCheckedKeys'相同 /* value: { default() { return []; } }, */ // 最多只能选择几个数量 maxItem: { type: Number }, // 最多只能选择几个数量-对象形配置 maxItemObj: { type: Object // default() { // return { level: 1, max: 3 }; // 第一层最多选中3个节点,第一层下面的节点仍旧可以选中,其余第一层节点下的节点无法选中 // } }, // 输入框宽度 width: { type: [Number, String], default: 160 }, // tree面板宽度 treeWidth: { type: Number, default: 200 }, // Select 组件头部内容 prefixLabel: { type: String }, // 是否多选 multiple: { type: Boolean, default: false }, // 默认要勾选tree的节点keys 必须是唯一值id的value // 适用于数据源由外部传入和lazy为false,如果是懒加载 lazy: true 远程获取必须在数据中增加'check'字段标明是否选中 defaultCheckedKeys: { type: Array, default() { return []; } }, // 定义外部 v-model 值,默认值 null 因为单选传入 String ,多选 array 并不确定 selectTreeValue: { default() { return null; } }, // 自定义样式名 ctCls: { type: String }, // 下拉面板的扩展样式 popoverClass: { type: String }, // 外部事件扩展 只有 'change' 选中值发生改变事件 listeners: { type: Object, default() { return {}; } }, // 显示字段 displayField: { type: String, default: 'name' }, // 值字段 valueField: { type: String, default: 'id' }, // 是否显示完整的路径(true 显示完整的路径,false 仅显示最后一级) showAllLevels: { type: Boolean, default: false }, // 是否显示搜索框 isRenderSearchInput: { type: Boolean, default: false }, // 自定义过滤函数 filterNodeMethodHandle: { type: Function }, // 是否显示下拉树选中的值到select的框中 isShowCheckSelectValue: { type: Boolean, default: true }, // 父子级联如果是false的情况下,是否需要父子联动(选中一个子节点级联选中对应的所有父级节点,取消某个父节点级联取消该节点下的所有子节点) checkStrictlyFalseCancelChildChecked: { type: Boolean, default: false }, // 动态宽度-单选时生效,设置后 width 参数将失效 isWidthAdapt: { type: Boolean, default: false } }, watch: { selectTreeValue(val) { if (_isNil(this.originalSelectTreeValue)) { this.originalSelectTreeValue = val; // 首次记录原始值 } if (_isNil(val) || val.length === 0) { this.clear(); } else { const checkedKeys = this.$refs[this.treeUserRef] .getTree() .getCheckedKeys(); if (_isArray(val) && this.multiple && !_isEqual(val, checkedKeys)) { if (val.length < checkedKeys.length) { // 多选 const aDifferenceList = _difference(checkedKeys, val); // 删除了哪几个值 const bDifferenceList = _difference(val, checkedKeys); // 添加哪几个值 this.outValueRemove(aDifferenceList); this.outValueAdd(bDifferenceList); this.$refs[this.treeUserRef].setCheckedKeys( this.curSelectValueList ); } else { const aDifferenceList = _difference(val, checkedKeys); // 添加哪几个值 const bDifferenceList = _difference(checkedKeys, val); // 去除哪几个值 this.outValueAdd(aDifferenceList); _forEach(aDifferenceList, aDiff => { this.getTree() .getTree() .setChecked(aDiff, true); }); _forEach(bDifferenceList, bDiff => { this.getTree() .getTree() .setChecked(bDiff, false); }); } return; } // 单选 if (!_isNil(val) && val !== this.curSelectValue) { this.setSingleNode(); } } } }, data() { this.popoverOffsetTop = 0; // 下拉面板的 offsetTop 偏差值 this.selectInputHeight = 0; // select 控件对应的 input 框的高度 this.treeProps = {}; this.originalSelectTreeValue = null; return { placement: 'bottom-start', treeUserRef: 'selectTree', popoverVisible: false, // 本地数据 curSelectNodeList: [], curSelectLabelList: [], curSelectValueList: [], // 复选 curSelectNode: null, curSelectLabel: '', // 单选 curSelectValue: '', curDefaultCheckedKeys: [...this.defaultCheckedKeys], treeValue: [], options: [], // [{ value: '', label: '' }] filterText: '' }; }, computed: { optionLabel() { const option = _find(this.options, option => { return option[this.valueField] === this.curSelectValue; }); return _get(option, this.displayField); }, prefixLabelVNode() { let prefixLabelVNode = null; const h = this.$createElement; if (this.prefixLabel && !this.isWidthAdapt) { prefixLabelVNode = [ h('template', { slot: 'prefix' }, [this.prefixLabel]) ]; } if (this.isWidthAdapt && !this.multiple) { prefixLabelVNode = h('template', { slot: 'prefix' }, [ this.optionLabel ]); } return prefixLabelVNode; } }, created() { if ( !_isEmpty(this.selectTreeValue) && (this.selectTreeValue !== '' || !_isNil(this.selectTreeValue)) ) { this.originalSelectTreeValue = this.selectTreeValue; // 首次记录原始值 } if (_has(this.$attrs, 'props')) { this.treeProps = _assign(this.$attrs.props, { label: this.displayField, value: this.valueField }); } else { this.treeProps = { label: this.displayField, value: this.valueField }; } }, methods: { /** * @desc 获取 tree 对象 */ getTree() { return this.$refs[this.treeUserRef]; }, /** * @desc 手动打开tree下拉面板 */ handOpenTree() { setTimeout(() => { this.popoverVisible = true; }, 0); }, /** * @desc 手动隐藏tree下拉面板 */ handCloseTree() { setTimeout(() => { this.popoverVisible = false; }, 0); }, /** * @desc 创建 el-popover */ createPopover() { const vNode = []; const h = this.$createElement; vNode.push( h( 'el-popover', { ref: 'base-select-tree-popover', props: { popperClass: `base-el-popover ${this.popoverClass}`, placement: this.placement, // title: '标题', width: this.treeWidth, trigger: 'click', value: this.popoverVisible // content: 'hello' }, on: { input: val => { this.popoverVisible = val; } } }, [ /* this.isRenderSearchInput ? h('el-input', { attrs: { placeholder: '请输入内容', maxlength: '30', clearable: true }, props: { value: this.filterText, showWordLimit: true }, on: { input: val => { this.filterText = val; this.getTree().getTree().filter(val); } } }) : h(), */ this.createTree(), h( 'div', { slot: 'reference', style: { height: '0px' }, ref: 'bbb' }, // 'click 激活' [] ) ] ) ); return vNode; }, /** * @desc 创建 el-tree 节点 */ createSelect() { const h = this.$createElement; const style = { width: _isString(this.width) ? this.width : `${this.width}px` }; // 文本框控件宽度 if (this.isWidthAdapt) { style.width = 'auto'; } let value = []; if (!this.isShowCheckSelectValue) { value = []; } if (this.multiple) { value = this.curSelectValueList; } else { value = this.curSelectValue; } const vNode = h( 'el-select', { ref: 'base-select-tree-ref', // key: `${this._uid}-base-select-tree-ref`, style, attrs: { id: this.$attrs.id, autofocus: this.$attrs.autofocus, placeholder: this.$attrs.placeholder }, class: { 'select-tree__autoWidth': this.isWidthAdapt && this.optionLabel }, props: _assign( {}, { // eslint-disable-next-line no-nested-ternary /* value: !this.isShowCheckSelectValue ? [] : this.multiple ? this.curSelectValueList : this.curSelectValue, */ value, // value: this.multiple // ? this.curSelectValueList // : this.curSelectValue, clearable: true, // 有清除按钮 multiple: this.multiple, // 设置多选,value对应为数组 'collapse-tags': true, // 合并多选 'popper-class': 'base-select-tree__popper' }, this.$attrs ), on: { 'hook:mounted': () => { this.selectInputHeight = this.$refs[ 'base-select-tree-ref' ].$el.offsetHeight; // input 框的高度 }, clear: () => { this.$emit('clearValue', this.multiple ? [] : ''); this.clear(); this.$refs[this.treeUserRef].clearChecked(); this.$emit('selectTreeChange', this.multiple ? [] : ''); this.change([]); this.setSelectPanel2InputOffsetTop(); this.$emit('clear', this.multiple ? [] : ''); this.$refs['base-select-tree-popover'].doClose(); }, 'remove-tag': tag => { this.$emit('clearValue', tag); const index = _findIndex( this.curSelectValueList, // eslint-disable-next-line no-shadow value => value === tag ); const optionIndex = _findIndex( this.options, item => item[this.valueField] === tag ); const cancelCheckedNodes = []; if (index !== -1) { cancelCheckedNodes.push(this.curSelectValueList[index]); this.curSelectNodeList.splice(index, 1); this.curSelectLabelList.splice(index, 1); this.curSelectValueList.splice(index, 1); } if (optionIndex !== -1) { this.options.splice(optionIndex, 1); } // this.$nextTick(() => { // this.$emit('selectTreeChange', this.curSelectValueList); // this.change(this.curSelectNodeList); // }); // this.$refs[this.treeUserRef].setCheckedKeys(cancelCheckedNodes); // this.$nextTick(() => { if (this.multiple && !_get(this.$attrs, 'check-strictly', true)) { const treeNode = this.$refs[this.treeUserRef] .getTree() .getNode(cancelCheckedNodes[0]); if (treeNode.parent.checked) { const valueIndex = _findIndex( this.curSelectValueList, v => v === _get(treeNode, `parent.data.${this.valueField}`) ); if (valueIndex !== -1) { cancelCheckedNodes.push( this.curSelectValueList[valueIndex] ); this.curSelectNodeList.splice(valueIndex, 1); this.curSelectLabelList.splice(valueIndex, 1); this.curSelectValueList.splice(valueIndex, 1); this.options.splice(valueIndex, 1); } } } // this.$emit('selectTreeChange', this.curSelectValueList); // this.change(this.curSelectNodeList); // }); this.$refs[this.treeUserRef].setCheckedKeys( this.curSelectValueList ); // this.$refs[this.treeUserRef] // .getTree() // .setChecked(cancelCheckedNodes[0], false); this.setSelectPanel2InputOffsetTop(); // this.$emit('remove-tag', this.multiple ? [] : ''); this.$emit('remove-tag', tag); // this.$nextTick(() => { this.$emit('selectTreeChange', [...this.curSelectValueList]); this.change(this.curSelectNodeList); // }); } }, nativeOn: { click: event => { const selectTree = this.$refs['base-select-tree-ref']; if ( !_isNil(selectTree) && !_isNil(selectTree.$el) && !_isNil(document.body.clientHeight) ) { if ( document.body.clientHeight - selectTree.$el.parentNode.offsetTop < 470 ) { this.placement = 'top-start'; } } if ( !_has(this.$attrs, 'disabled') || (_has(this.$attrs, 'disabled') && this.$attrs.disabled === false) ) { this.$refs['base-select-tree-ref'].blur(); this.$refs.bbb.click(); // 如果是 el-button ,那么自动触发 click 事件 `this.$refs.bbb.$el.click();` event.stopPropagation(); event.preventDefault(); return false; } return true; } } }, [ this.prefixLabelVNode, this.createOptions(), h( 'div', { class: 'base-select-tree-down-empty', slot: 'empty', style: { display: 'none' } }, [] ) ] ); return vNode; }, /** * @desc 创建 el-option 节点 */ createOptions() { const h = this.$createElement; const vNode = this.options.map(option => { return h('el-option', { style: { /* width: `${this.treeWidth}px`, height: 'auto', 'max-height': `${this.treeHeight}px`, 'background-color': this.backgroundColor, padding: '0px', overflow: 'auto', */ display: 'absolute', top: '0px', left: '0px', height: '0px', 'z-index': '-100' // display: 'none' }, props: { key: option[this.valueField], label: option[this.displayField], value: option[this.valueField] }, on: { 'hook:mounted': () => {} } }); }); return vNode; }, /** * @desc 创建下拉 tree 控件 */ createTree() { const h = this.$createElement; const that = this; return h( 'base-tree', { /* style: { height: '100%', overflow: 'auto', 'font-weight': 'normal' }, */ // class: 'select-tree-panel', ref: this.treeUserRef, attrs: { defaultCheckedKeys: this.curDefaultCheckedKeys, checkStrictly: _get(this.$attrs, 'check-strictly', this.multiple), // 在显示复选框的情况下,是否严格的遵循父子不互相关联的做法,默认为 false showCheckbox: this.multiple, // 出现复选框 'show-checkbox': this.multiple, ..._omit(this.$attrs, [ 'defaultCheckedKeys', 'checkStrictly', 'showCheckbox', 'default-checked-keys', 'check-strictly', 'show-checkbox' ]), 'filter-node-method': (value, data) => { if (!value) { return true; } if (!_isNil(this.filterNodeMethodHandle)) { return this.filterNodeMethodHandle(value, data); } return _get(data, this.displayField).indexOf(value) !== -1; } }, props: _assign( {}, { // displayField: this.displayField, // valueField: this.valueField, // treeValue: this.treeValue, // v-model value 属性 listeners: { nodeClick: (record, node, tree) => { // 使 input 失去焦点,并隐藏下拉框 this.$refs['base-select-tree-ref'].blur(); this.$refs['base-select-tree-popover'].doClose(); const eventName = _has(this.$listeners, 'nodeClick') ? 'nodeClick' : 'node-click'; this.$emit(eventName, record, node, tree); }, checkChange: (record, checked) => { if ( this.curSelectValueList.includes(record[this.valueField]) && !checked ) { const index = this.curSelectValueList.findIndex( value => value === record[this.valueField] ); const optionIndex = this.options.findIndex( item => item[this.valueField] === record[this.valueField] ); if (index !== -1) { this.curSelectValueList.splice(index, 1); this.curSelectLabelList.splice(index, 1); this.curSelectNodeList.splice(index, 1); } if (optionIndex !== -1) { this.options.splice(optionIndex, 1); } } } } }, this.$attrs, { props: this.treeProps, nodeKey: this.getNodeKey() } ), on: { // 数据加载完成 afterLoadStore: () => { // 默认选中 if (!_isNil(that.selectTreeValue)) { if (that.multiple) { that.curDefaultCheckedKeys.push(...that.selectTreeValue); } else { // that.curDefaultCheckedKeys.push(that.selectTreeValue); // 单选不用设置,因为单选其实没有选中的效果 } setTimeout(() => { if (that.multiple) { const nodes = that.$refs[ that.treeUserRef ].getCheckedNodes(); if (!_isEmpty(nodes)) { // eslint-disable-next-line no-restricted-syntax for (let i = 0, len = nodes.length; i < len; i += 1) { const treeNode = that .getTree() .getTree() .getNode(nodes[i][that.valueField]); const levelStr = that .getTree() .getNodeParentLevel(treeNode); that.options.push({ [that.valueField]: nodes[i][that.valueField], [that.displayField]: that.showAllLevels ? levelStr : nodes[i][that.displayField] }); if (that.multiple) { that.curSelectValueList.push( nodes[i][that.valueField] ); that.curSelectLabelList.push( nodes[i][that.displayField] ); that.curSelectNodeList.push(nodes[i]); if ( !_get(this.$attrs, 'check-strictly', this.multiple) ) { // 父子级联 const vValues = that.getCheckedLeafNodes(); this.$emit('selectTreeChange', vValues); // 多选 } else { const checkedValues = _map( this.$refs[this.treeUserRef].getCheckedNodes(), node => { return _get(node, this.valueField); } ); // 多选但不是父子级联把勾选的节点都传递出去 this.$emit('selectTreeChange', checkedValues); } } } if (!that.multiple) { that.curSelectValue = nodes[0][that.valueField]; } } } else { // 单选 that.setSingleNode(); } }, 0); } setTimeout(() => { this.$emit('afterLoadStore'); }, 0); }, check: (node, treeCheckedNode) => { this.$emit('check', node, treeCheckedNode); // 多选-点击复选框 // this.$refs.bbb.click(); // 防止下拉树面板在点击后隐藏 this.setSelectPanel2InputOffsetTop(); if (this.multiple) { const checkedKeys = this.$refs[this.treeUserRef] .getTree() .getCheckedKeys(); // 操作最大的选中数量 if ( !_isNil(this.maxItem) && checkedKeys.length > this.maxItem ) { this.$refs[this.treeUserRef] .getTree() .setChecked(node[this.valueField], false); return; } if (!_isNil(this.maxItemObj)) { const treeNode = this.$refs[this.treeUserRef] .getTree() .getNode(_get(node, this.valueField)); const level = _get(this.maxItemObj, 'level'); const max = _get(this.maxItemObj, 'max'); const checkedNodes = _map(checkedKeys, v => this.$refs[this.treeUserRef].getTree().getNode(v) ); const levelNodes = _filter( checkedNodes, v => v.level === level ); if (levelNodes.length > max) { this.$refs[this.treeUserRef] .getTree() .setChecked(node[this.valueField], false); return; } if (levelNodes.length === max && treeNode.level > level) { const isInclude = this.getTree().isTreeNodesIncludeNode( levelNodes, treeNode ); // 选中的节点是否在指定大类的小类中,如果是则选中否则取消选中 // 不包含在里面取消当前选中的节点 if (!isInclude) { this.cancelChecked(node); return; } } if (treeNode.level > level && levelNodes.length === max) { const isInclude = this.getTree().isTreeNodesIncludeNode( levelNodes, treeNode ); // 选中的节点是否在指定大类的小类中,如果是则选中否则取消选中 // 不包含在里面取消当前选中的节点 if (!isInclude) { this.cancelChecked(node); return; } } } if (!_get(this.$attrs, 'check-strictly', this.multiple)) { // 多选,父子级联 const options = []; this.curSelectLabelList = []; this.curSelectValueList = []; this.options = []; this.curSelectNodeList = treeCheckedNode.checkedNodes; // eslint-disable-next-line no-restricted-syntax for ( let i = 0, len = this.curSelectNodeList.length; i < len; i += 1 ) { const sChildField = _get( this.treeProps, 'children', 'children' ); const children = _get( this.curSelectNodeList[i], sChildField ); if (_isNil(children) || _isEmpty(children)) { const name = _get( this.curSelectNodeList[i], this.displayField ); const value = _get( this.curSelectNodeList[i], this.valueField ); this.curSelectLabelList.push(name); this.curSelectValueList.push(value); const treeNode = this.getTree() .getTree() .getNode(value); const levelStr = this.getTree().getNodeParentLevel( treeNode ); options.push({ [this.displayField]: this.showAllLevels ? levelStr : name, [this.valueField]: value }); } } this.options = options; } else { const treeNode = this.getTree() .getTree() .getNode(node[this.valueField]); // 父子不级联 if ( this.checkStrictlyFalseCancelChildChecked && !treeNode.checked ) { // 取消选中 const childCheckNodes = this.getTree().getNodeCheckedChild( treeNode ); // eslint-disable-next-line no-restricted-syntax for ( let i = 0, len = childCheckNodes.length; i < len; i += 1 ) { this.getTree() .getTree() .setChecked(childCheckNodes[i], false); const index = _findIndex( this.curSelectValueList, v => v === childCheckNodes[i] ); if (index !== -1) { this.curSelectNodeList.splice(index, 1); this.curSelectLabelList.splice(index, 1); this.curSelectValueList.splice(index, 1); this.options.splice(index, 1); } } } if ( this.checkStrictlyFalseCancelChildChecked && treeNode.checked ) { // 级联选中 const parentTreeNodes = this.getTree().getNodeParentNodes( treeNode ); const checkedHandle = () => { // eslint-disable-next-line no-restricted-syntax for ( let i = 0, len = parentTreeNodes.length; i < len; i += 1 ) { // eslint-disable-next-line no-shadow const node = parentTreeNodes[i]; if (!node.checked) { // this.$nextTick(() => { this.$refs[this.treeUserRef] .getTree() .setChecked(node.data[this.valueField], true); if ( !_includes( this.curSelectValueList, node.data[this.valueField] ) ) { this.curSelectNodeList.push(node.data); this.curSelectLabelList.push( node.data[this.displayField] ); this.curSelectValueList.push( node.data[this.valueField] ); this.options.push({ [this.displayField]: this.showAllLevels ? this.getTree().getNodeParentLevel(node) : node.data[this.displayField], [this.valueField]: node.data[this.valueField] }); } // }); } } }; checkedHandle(); /* if (_isNil(this.maxItemObj)) { checkedHandle(); } else { const level = _get(this.maxItemObj, 'level'); const max = _get(this.maxItemObj, 'max'); const checkedNodes = _map(checkedKeys, v => this.$refs[this.treeUserRef].getTree().getNode(v) ); const levelNodes = _filter( checkedNodes, v => v.level === level ); if (levelNodes.length < max) { checkedHandle(); } } */ } if (!_includes(checkedKeys, node[this.valueField])) { this.$emit('selectTreeChange', [ ...this.curSelectValueList ]); this.change(this.curSelectNodeList); return; } this.curSelectNodeList.push(node); this.curSelectLabelList.push(node[this.displayField]); this.curSelectValueList.push(node[this.valueField]); const levelStr = this.showAllLevels ? this.getTree().getNodeParentLevel(node) : node[this.displayField]; this.options.push({ [this.displayField]: levelStr, [this.valueField]: node[this.valueField] }); } this.$emit('selectTreeChange', [...this.curSelectValueList]); // 这里注意需要返回一个新数组,否则我们在操作 this.curSelectValueList 这个数组 push、splice 的元素后会触发 selectTreeValue 的 watch 监听 this.change([...this.curSelectNodeList]); } }, // v-model input事件 currentChange: (record = {}, curNode = {}) => { // 单选 if (!this.multiple) { if ( (_has(this.$attrs, 'isSelectedLastNode') && this.$attrs.isSelectedLastNode) || (_has(this.$attrs, 'is-selected-last-node') && this.$attrs['is-selected-last-node']) ) { const treeProps = this.$refs[this.treeUserRef].defaultProps; // 设置需要选中最里面的节点 if ( _has(record, treeProps.children) && !_isNil(_get(record, treeProps.children)) && _get(record, treeProps.children).length !== 0 ) { return; } } const isSelectedLevel = _has(this.$attrs, 'selectedLevel') || _has(this.$attrs, 'selected-level'); const selectedLevelVal = this.$attrs.selectedLevel || this.$attrs['selected-level']; const isDisabledNodes = _has(this.$attrs, 'disabledNodes') || _has(this.$attrs, 'disabled-nodes'); const disabledNodesVal = this.$attrs.disabledNodes || this.$attrs['disabled-nodes']; if ( (isSelectedLevel && selectedLevelVal && curNode.level !== selectedLevelVal) || (isDisabledNodes && !_isEmpty(disabledNodesVal) && _includes( disabledNodesVal, _get(curNode, `data.${this.valueField}`) )) ) { return; } if ( _has(curNode, 'data.disabled') && curNode.data.disabled === true ) { return; } const node = this.getTree() .getTree() .getNode(record[this.valueField]); const levelStr = this.getTree().getNodeParentLevel(node); this.options = []; this.options.push({ [this.displayField]: this.showAllLevels ? levelStr : record[this.displayField], [this.valueField]: record[this.valueField] }); this.curSelectValue = record[this.valueField]; this.curSelectLabel = record[this.displayField]; this.$emit('selectTreeChange', this.curSelectValue); this.change({ [this.displayField]: record[this.displayField], [this.valueField]: record[this.valueField], ..._omit(record, [this.displayField, this.valueField]) }); } }, // 清空数据事件 clearData: () => { this.clear(); this.$refs[this.treeUserRef].clearChecked(); this.$emit('selectTreeChange', this.multiple ? [] : ''); this.change([]); this.setSelectPanel2InputOffsetTop(); this.$emit('clear', this.multiple ? [] : ''); } }, scopedSlots: _has(this.$scopedSlots, 'default') ? { default: props => { return this.$scopedSlots.default(props); }, handleIconScope: props => { return _has(this.$scopedSlots, 'handleMenuScope') ? this.$scopedSlots.handleMenuScope(props) : h(); } } : undefined }, [ this.isRenderSearchInput ? h('el-input', { slot: 'searchInputSlot', class: 'select-tree__input', attrs: { placeholder: '请输入内容', maxlength: '30', clearable: true }, props: { value: this.filterText, showWordLimit: true }, on: { input: val => { this.filterText = val; this.getTree() .getTree() .filter(val); } } }) : h() ] ); }, getNodeKey() { return _get(this.$attrs, 'node-key', this.valueField); }, /** * @desc 设置单选-选中效果(单选其实在树上面没有选中效果) */ setSingleNode() { const that = this; if ( !_isNil(that.$refs[that.treeUserRef]) && !_isNil(that.$refs[that.treeUserRef].getTree()) && !_isNil(that.selectTreeValue) ) { const elTree = that.$refs[that.treeUserRef].getTree(); const checkedNode = elTree.getNode(that.selectTreeValue); if (!_isNil(checkedNode)) { const record = checkedNode; this.options = []; this.options.push({ [that.displayField]: this.showAllLevels ? this.getTree().getNodeParentLevel(checkedNode) : record.data[that.displayField], [that.valueField]: record.data[that.valueField] }); that.curSelectValue = record.data[that.valueField]; that.curSelectLabel = record.data[that.displayField]; that.$emit('selectTreeChange', that.curSelectValue); that.change({ [that.displayField]: record.data[that.displayField], [that.valueField]: record.data[that.valueField] }); elTree.setCurrentKey(that.selectTreeValue); // 设置单选选中效果 } } }, /** * @desc 计算下拉面板和input框之间的高度差值 */ setSelectPanel2InputOffsetTop() { setTimeout(() => { const popoverEl = this.$refs['base-select-tree-popover'].$el; if (!_isNil(popoverEl) && !_isNil(popoverEl.childNodes)) { const selectInputHeight = this.$refs['base-select-tree-ref'].$el .clientHeight; // input 框的高度 // console.info('abc ', this.$refs['base-select-tree-ref']); const oldTopNum = this.$refs[ this.treeUserRef ].$el.parentNode.style.top.replace('px', ''); // console.info(this.selectInputHeight, selectInputHeight); if (selectInputHeight > this.selectInputHeight) { const dValue = selectInputHeight - this.selectInputHeight; // 差值 this.$refs[ this.treeUserRef ].$el.parentNode.style.top = `${_toNumber(oldTopNum) + _toNumber(dValue)}px`; } else if (selectInputHeight <= this.selectInputHeight) { const dValue = this.selectInputHeight - selectInputHeight; // console.info('================', dValue); if (dValue !== 0) { this.$refs[ this.treeUserRef ].$el.parentNode.style.top = `${_toNumber(oldTopNum) - _toNumber(dValue)}px`; } } this.selectInputHeight = selectInputHeight; } }, 100); // console.info('abc ', this.$refs.bbb.offsetTop); /* console.info(this.$refs[this.treeUserRef].$el.parentNode.style.top.replace('px', '')); console.info('33333333 ', this.$refs['base-select-tree-popover'].$el.childNodes[0].offsetTop); console.info('4444 ', this.$refs[this.treeUserRef].$el.parentNode); */ }, /** * @desc 清空 */ clear() { if (!_isEmpty(this.curSelectNodeList)) { this.curSelectNodeList = []; this.curSelectLabelList = []; this.curSelectValueList = []; this.curSelectNode = null; this.curSelectLabel = ''; this.curSelectValue = ''; this.curDefaultCheckedKeys = [...this.defaultCheckedKeys]; this.treeValue = []; this.options = []; const baseTree = this.$refs[this.treeUserRef].getTree(); if (!_isEmpty(baseTree.getCheckedKeys())) { if (this.multiple) { baseTree.setCheckedKeys([]); } else { baseTree.setCurrentKey(null); } } } if ( !this.multiple && (this.selectTreeValue === '' || _isNil(this.selectTreeValue)) ) { this.curSelectNode = null; this.curSelectLabel = ''; this.curSelectValue = ''; const baseTree = this.$refs[this.treeUserRef].getTree(); if (!_isNil(baseTree.getCurrentKey())) { baseTree.setCurrentKey(null); } } }, /** * @desc 重置 */ reset() { this.clear(); this.$nextTick(() => { // 默认勾选的节点的 key 的数组 if ( !_isEmpty(this.defaultCheckedKeys) || !_isEmpty(this.originalSelectTreeValue) ) { const checkedNodeKeys = [...this.defaultCheckedKeys]; if (this.multiple) { checkedNodeKeys.push(...this.originalSelectTreeValue); } else { checkedNodeKeys.push(this.originalSelectTreeValue); } if (!_isEmpty(checkedNodeKeys)) { const baseTree = this.$refs[this.treeUserRef].getTree(); baseTree.setCheckedKeys(checkedNodeKeys); const nodes = this.$refs[this.treeUserRef].getCheckedNodes(); const childFieldName = _get(this.treeProps, 'children', 'children'); _forEach(nodes, node => { if ( !_has(node, childFieldName) || _isNil(node[childFieldName]) || _isEmpty(node[childFieldName]) ) { this.curSelectNodeList.push(node); this.curSelectLabelList.push(node[this.displayField]); this.curSelectValueList.push(node[this.valueField]); const levelStr = this.showAllLevels ? this.getTree().getNodeParentLevel(node) : node[this.displayField]; this.options.push({ [this.displayField]: levelStr, [this.valueField]: node[this.valueField] }); } }); } if (this.multiple) { const checkedNodes = this.getCheckedLeafNodes(); this.$emit('selectTreeChange', checkedNodes); } else { this.$emit('selectTreeChange', this.originalSelectTreeValue); } } }); }, // 通过 key 设置某个节点的勾选状态,使用此方法必须设置 node-key 属性 setChecked(nodeId, checked = true) { const nodeIdIndex = _findIndex( this.curSelectValueList, curSelectValueItem => curSelectValueItem === nodeId ); if (nodeIdIndex !== -1) { this.$refs[this.treeUserRef].getTree().setChecked(nodeId, checked); // 取消选中 this.curSelectValueList.splice(nodeIdIndex, 1); this.curSelectLabelList.splice(nodeIdIndex, 1); this.curSelectNodeList.splice(nodeIdIndex, 1); this.$emit('selectTreeChange', this.curSelectValueList); } }, getOptions() { return JSON.parse(JSON.stringify(this.options)); }, // 获取所有选中的子节点-多选情况下起效 getCheckedLeafNodes( { field } = { field: _get(this.$attrs, 'node-key', this.valueField) } ) { if (this.multiple) { const nodes = this.$refs[this.treeUserRef].getCheckedNodes(); const childFieldName = _get(this.treeProps, 'children', 'children'); const leafNodeKeys = []; _forEach(nodes, node => { if ( !_has(node, childFieldName) || _isNil(node[childFieldName]) || _isEmpty(node[childFieldName]) ) { leafNodeKeys.push(_get(node, field)); } }); return leafNodeKeys; } return ''; }, // 获取所有选中的节点 getCheckedNodes() { const nodes = this.$refs[this.treeUserRef].getCheckedNodes(); return _map(nodes, node => { return { ...node }; }); }, // 获取base-select-tree组件当前是打开还是关闭状态 getSelectShowPopper() { const { showPopper } = this.$refs['base-select-tree-popover']; return showPopper; }, /** * @desc 外部 v-model 直接操作值 */ outValueRemove(aDifferenceList) { _forEach(aDifferenceList, aDifferenceVal => { const index = _findIndex( this.curSelectValueList, v => v === aDifferenceVal ); if (index !== -1) { this.curSelectValueList.splice(index, 1); this.curSelectLabelList.splice(index, 1); this.curSelectNodeList.splice(index, 1); this.options.splice(index, 1); } }); }, /** * @desc 外部 v-model 直接操作值 */ outValueAdd(aDifferenceList) { _forEach(aDifferenceList, aDifferenceVal => { const treeNode = this.getTree() .getTree() .getNode(aDifferenceVal); if (!_isNil(treeNode)) { const data = _get(treeNode, 'data', {}); this.curSelectNodeList.push(data); this.curSelectLabelList.push(data[this.displayField]); this.curSelectValueList.push(data[this.valueField]); const levelStr = this.getTree().getNodeParentLevel(treeNode); this.options.push({ [this.valueField]: data[this.valueField], [this.displayField]: this.showAllLevels ? levelStr : data[this.displayField] }); } }); }, /** * @desc 自定义change事件 * @param {Array|String} val */ change(val) { if ('change' in this.listeners) { this.listeners.change(val); } }, /** * @desc 某个树节点(data对象)取消选中 */ cancelChecked(treeNodeData) { this.$refs[this.treeUserRef] .getTree() .setChecked(treeNodeData[this.valueField], false); const index = _findIndex( this.curSelectValueList, v => v === treeNodeData[this.valueField] ); if (index !== -1) { this.curSelectNodeList.splice(index, 1); this.curSelectLabelList.splice(index, 1); this.curSelectValueList.splice(index, 1); this.options.splice(index, 1); } }, // 手动关闭下拉框 doClose() { const popoverRef = this.$refs['base-select-tree-popover']; if (!_isNil(popoverRef) && popoverRef.showPopper) { this.$refs['base-select-tree-ref'].blur(); popoverRef.doClose(); } } }, render(h) { const styleWidth = {}; if (this.isWidthAdapt) { styleWidth.width = 'auto'; } else { styleWidth.width = _isString(this.width) ? this.width : `${this.width}px`; } return h( 'div', { ref: 'base-select-panel', style: styleWidth, class: { 'base-select-tree': true, [this.ctCls]: this.ctCls } }, [this.createSelect(), this.createPopover()] ); } }; BaseSelectTree.install = function(Vue, ElComponents) { // 用于按需加载的时候独立使用 devConsole(`按需加载独立组件:${BaseSelectTree.name}`); if (_isArray(ElComponents) && !_isEmpty(ElComponents)) { for (let i = 0; i < ElComponents.length; i++) { if (ElComponents[i].name !== BaseSelectTree.name) { Vue.use(ElComponents[i]); } } } Vue.component(BaseSelectTree.name, BaseSelectTree); }; export { BaseSelectTree };